Merge change I663d4cb7 into eclair

* changes:
  Update the project creation (from the command line):
diff --git a/ndk/build/toolchains/arm-eabi-4.2.1/setup.mk b/ndk/build/toolchains/arm-eabi-4.2.1/setup.mk
index 4c10c07..f5ca8b4 100644
--- a/ndk/build/toolchains/arm-eabi-4.2.1/setup.mk
+++ b/ndk/build/toolchains/arm-eabi-4.2.1/setup.mk
@@ -74,7 +74,7 @@
 TARGET_ARFLAGS := crs
 
 TARGET_LIBGCC := $(shell $(TARGET_CC) -mthumb-interwork -print-libgcc-file-name)
-TARGET_LDLIBS := -Wl,-rpath-link=$(SYSROOT)/usr/lib $(TARGET_LIBGCC)
+TARGET_LDLIBS := -Wl,-rpath-link=$(SYSROOT)/usr/lib
 
 # These flags are used to ensure that a binary doesn't reference undefined
 # flags.
@@ -84,6 +84,15 @@
 # this toolchain's generated binaries
 TARGET_ABI_SUBDIR := armeabi
 
+# NOTE: Ensure that TARGET_LIBGCC is placed after all private objects
+#       and static libraries, but before any other library in the link
+#       command line when generating shared libraries and executables.
+#
+#       This ensures that all libgcc.a functions required by the target
+#       will be included into it, instead of relying on what's available
+#       on other libraries like libc.so, which may change between system
+#       releases due to toolchain or library changes.
+#
 define cmd-build-shared-library
 $(TARGET_CC) \
     -nostdlib -Wl,-soname,$(notdir $@) \
@@ -93,6 +102,7 @@
     $(PRIVATE_WHOLE_STATIC_LIBRARIES) \
     -Wl,--no-whole-archive \
     $(PRIVATE_STATIC_LIBRARIES) \
+    $(TARGET_LIBGCC) \
     $(PRIVATE_SHARED_LIBRARIES) \
     $(PRIVATE_LDFLAGS) \
     $(PRIVATE_LDLIBS) \
@@ -105,10 +115,11 @@
     -Wl,-dynamic-linker,/system/bin/linker \
     -Wl,--gc-sections \
     -Wl,-z,nocopyreloc \
-    $(PRIVATE_SHARED_LIBRARIES) \
     $(TARGET_CRTBEGIN_DYNAMIC_O) \
     $(PRIVATE_OBJECTS) \
     $(PRIVATE_STATIC_LIBRARIES) \
+    $(TARGET_LIBGCC) \
+    $(PRIVATE_SHARED_LIBRARIES) \
     $(PRIVATE_LDFLAGS) \
     $(PRIVATE_LDLIBS) \
     $(TARGET_CRTEND_O) \
diff --git a/ndk/docs/CHANGES.TXT b/ndk/docs/CHANGES.TXT
index faad11d..c03fc60 100644
--- a/ndk/docs/CHANGES.TXT
+++ b/ndk/docs/CHANGES.TXT
@@ -1,6 +1,14 @@
 Android NDK ChangeLog:
 
 -------------------------------------------------------------------------------
+current version
+
+IMPORTANT BUG FIXES:
+
+- Make target shared libraries portable to systems that don't use the exact same
+  toolchain (GCC 4.2.1) .
+
+-------------------------------------------------------------------------------
 android-ndk-1.6_r1
 
 IMPORTANT BUG FIXES:
@@ -24,7 +32,7 @@
   in $(CLEAR_VARS) script.
 
 
-IMPORTANT CHANGES
+IMPORTANT CHANGES:
 
 - The 'sources' directory is gone. The NDK build system now looks for
   $(APP_PROJECT_PATH)/jni/Android.mk by default. You can override this with
diff --git a/testrunner/test_defs.xml b/testrunner/test_defs.xml
index 2c4801c..6d38d1d 100644
--- a/testrunner/test_defs.xml
+++ b/testrunner/test_defs.xml
@@ -368,6 +368,13 @@
     package="com.android.providers.contacts.tests"
     coverage_target="ContactsProvider" />
 
+<test name="contacts"
+    build_path="packages/apps/Contacts"
+    package="com.android.contacts.tests"
+    runner="android.test.InstrumentationTestRunner"
+    coverage_target="Contacts"
+    description="Tests for the Contacts app." />
+
 <test name="gcontactsprov"
     build_path="packages/providers/GoogleContactsProvider/tests"
     package="com.android.providers.contactstests"
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index f17b3c8..047c985 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -1026,10 +1026,16 @@
 
                         progress.setTaskName(Messages.AdtPlugin_Parsing_Resources);
 
-                        int n = sdk.getTargets().length;
+                        final IAndroidTarget[] targets = sdk.getTargets();
+                        final int n = targets.length;
                         if (n > 0) {
+                            // load the layout devices.
+                            sdk.parseAddOnLayoutDevices();
+
+                            // load the rest of the targes.
+                            // TODO: make this on-demand.
                             int w = 60 / n;
-                            for (IAndroidTarget target : sdk.getTargets()) {
+                            for (IAndroidTarget target : targets) {
                                 SubMonitor p2 = progress.newChild(w);
                                 IStatus status = new AndroidTargetParser(target).run(p2);
                                 if (status.getCode() != IStatus.OK) {
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalEditorPart.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalEditorPart.java
index cab6829..4953f7e 100755
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalEditorPart.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalEditorPart.java
@@ -975,6 +975,7 @@
             AndroidTargetData data = currentSdk.getTargetData(target);

             if (data != null) {

                 LayoutBridge bridge = data.getLayoutBridge();

+                mConfigComposite.reloadDevices();

                 mConfigComposite.setClippingSupport(bridge.apiLevel >= 4);

             }

         }

diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalLayoutEditor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalLayoutEditor.java
index 1c9cac3..6d210a8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalLayoutEditor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/GraphicalLayoutEditor.java
@@ -738,6 +738,7 @@
             AndroidTargetData data = currentSdk.getTargetData(target);
             if (data != null) {
                 LayoutBridge bridge = data.getLayoutBridge();
+                mConfigComposite.reloadDevices();
                 mConfigComposite.setClippingSupport(bridge.apiLevel >= 4);
             }
         }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
index fe98ee8..1cd301c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationComposite.java
@@ -28,6 +28,7 @@
 import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
 import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources;
 import com.android.ide.eclipse.adt.internal.sdk.DeviceConfiguration;
+import com.android.ide.eclipse.adt.internal.sdk.Sdk;
 import com.android.ide.eclipse.adt.internal.ui.ConfigurationSelector.LanguageRegionVerifier;
 import com.android.layoutlib.api.IResourceValue;
 import com.android.layoutlib.api.IStyleResourceValue;
@@ -46,6 +47,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
@@ -73,7 +75,7 @@
     /** The {@link FolderConfiguration} representing the state of the UI controls */
     private final FolderConfiguration mCurrentConfig = new FolderConfiguration();
 
-    private DeviceConfiguration[] mDevices;
+    private List<DeviceConfiguration> mDevices;
 
     private final ArrayList<ResourceQualifier[] > mLocaleList =
         new ArrayList<ResourceQualifier[]>();
@@ -103,7 +105,9 @@
     public ConfigurationComposite(IConfigListener listener, Composite parent, int style) {
         super(parent, style);
         mListener = listener;
-        mDevices = DeviceConfiguration.getDevices();
+        if (Sdk.getCurrent() != null) {
+            mDevices = Sdk.getCurrent().getLayoutDevices();
+        }
 
         GridLayout gl;
         GridData gd;
@@ -141,12 +145,6 @@
 
         new Label(this, SWT.NONE).setText("Devices");
         mDeviceList = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
-        // fill with the devices
-        for (DeviceConfiguration device : mDevices) {
-            mDeviceList.add(device.getName());
-        }
-
-        mDeviceList.select(0);
         mDeviceList.setLayoutData(new GridData(
                 GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
         mDeviceList.addSelectionListener(new SelectionAdapter() {
@@ -158,15 +156,6 @@
 
         new Label(this, SWT.NONE).setText("Config");
         mDeviceConfigs = new Combo(this, SWT.DROP_DOWN | SWT.READ_ONLY);
-        Map<String, FolderConfiguration> configs = mDevices[0].getConfigs();
-        Set<String> configNames = configs.keySet();
-        for (String name : configNames) {
-            mDeviceConfigs.add(name);
-        }
-        mDeviceConfigs.select(0);
-        if (configNames.size() == 1) {
-            mDeviceConfigs.setEnabled(false);
-        }
         mDeviceConfigs.setLayoutData(new GridData(
                 GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
         mDeviceConfigs.addSelectionListener(new SelectionAdapter() {
@@ -224,9 +213,12 @@
             }
         });
 
+        initUiWithDevices();
+
         onDeviceConfigChange();
     }
 
+
     public FolderConfiguration getCurrentConfig() {
         return mCurrentConfig;
     }
@@ -458,6 +450,44 @@
     }
 
     /**
+     * Reloads the list of {@link DeviceConfiguration} from the {@link Sdk}.
+     */
+    public void reloadDevices() {
+        mDevices = Sdk.getCurrent().getLayoutDevices();
+        initUiWithDevices();
+        onDeviceChange();
+    }
+
+    /**
+     * Init the UI with the list of Devices.
+     */
+    private void initUiWithDevices() {
+        // remove older devices if applicable
+        mDeviceList.removeAll();
+        mDeviceConfigs.removeAll();
+
+        // fill with the devices
+        if (mDevices != null) {
+            for (DeviceConfiguration device : mDevices) {
+                mDeviceList.add(device.getName());
+            }
+            mDeviceList.select(0);
+
+            if (mDevices.size() > 0) {
+                Map<String, FolderConfiguration> configs = mDevices.get(0).getConfigs();
+                Set<String> configNames = configs.keySet();
+                for (String name : configNames) {
+                    mDeviceConfigs.add(name);
+                }
+                mDeviceConfigs.select(0);
+                if (configNames.size() == 1) {
+                    mDeviceConfigs.setEnabled(false);
+                }
+            }
+        }
+    }
+
+    /**
      * Call back for language combo selection
      */
     private void onLocaleChange() {
@@ -481,7 +511,7 @@
     private void onDeviceChange() {
 
         int deviceIndex = mDeviceList.getSelectionIndex();
-        DeviceConfiguration device = mDevices[deviceIndex];
+        DeviceConfiguration device = mDevices.get(deviceIndex);
 
         mDeviceConfigs.removeAll();
 
@@ -499,28 +529,30 @@
     }
 
     private void onDeviceConfigChange() {
-        int deviceIndex = mDeviceList.getSelectionIndex();
-        DeviceConfiguration device = mDevices[deviceIndex];
+        if (mDevices != null) {
+            int deviceIndex = mDeviceList.getSelectionIndex();
+            DeviceConfiguration device = mDevices.get(deviceIndex);
 
-        int configIndex = mDeviceConfigs.getSelectionIndex();
-        String name = mDeviceConfigs.getItem(configIndex);
-        FolderConfiguration config = device.getConfigs().get(name);
+            int configIndex = mDeviceConfigs.getSelectionIndex();
+            String name = mDeviceConfigs.getItem(configIndex);
+            FolderConfiguration config = device.getConfigs().get(name);
 
-        // get the current qualifiers from the current config
-        LanguageQualifier lang = mCurrentConfig.getLanguageQualifier();
-        RegionQualifier region = mCurrentConfig.getRegionQualifier();
-        VersionQualifier version = mCurrentConfig.getVersionQualifier();
+            // get the current qualifiers from the current config
+            LanguageQualifier lang = mCurrentConfig.getLanguageQualifier();
+            RegionQualifier region = mCurrentConfig.getRegionQualifier();
+            VersionQualifier version = mCurrentConfig.getVersionQualifier();
 
-        // replace the config with the one from the device
-        mCurrentConfig.set(config);
+            // replace the config with the one from the device
+            mCurrentConfig.set(config);
 
-        // and put back the rest of the qualifiers
-        mCurrentConfig.addQualifier(lang);
-        mCurrentConfig.addQualifier(region);
-        mCurrentConfig.addQualifier(version);
+            // and put back the rest of the qualifiers
+            mCurrentConfig.addQualifier(lang);
+            mCurrentConfig.addQualifier(region);
+            mCurrentConfig.addQualifier(version);
 
-        if (mListener != null) {
-            mListener.onConfigurationChange();
+            if (mListener != null) {
+                mListener.onConfigurationChange();
+            }
         }
     }
 
@@ -603,3 +635,4 @@
         return false;
     }
 }
+
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/KeyboardStateQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/KeyboardStateQualifier.java
index 2777328..e00428e 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/KeyboardStateQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/KeyboardStateQualifier.java
@@ -53,7 +53,7 @@
          * @param value The qualifier value.
          * @return the enum for the qualifier value or null if no matching was found.
          */
-        static KeyboardState getEnum(String value) {
+        public static KeyboardState getEnum(String value) {
             for (KeyboardState orient : values()) {
                 if (orient.mValue.equals(value)) {
                     return orient;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/NavigationMethodQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/NavigationMethodQualifier.java
index 9363e87..50cb9cb 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/NavigationMethodQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/NavigationMethodQualifier.java
@@ -54,7 +54,7 @@
          * @param value The qualifier value.
          * @return the enum for the qualifier value or null if no matching was found.
          */
-        static NavigationMethod getEnum(String value) {
+        public static NavigationMethod getEnum(String value) {
             for (NavigationMethod orient : values()) {
                 if (orient.mValue.equals(value)) {
                     return orient;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/PixelDensityQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/PixelDensityQualifier.java
index f82a6ff..ed33994 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/PixelDensityQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/PixelDensityQualifier.java
@@ -61,7 +61,7 @@
          * @param value The qualifier value.
          * @return the enum for the qualifier value or null if no matching was found.
          */
-        static Density getEnum(String value) {
+        public static Density getEnum(String value) {
             for (Density orient : values()) {
                 if (orient.mValue.equals(value)) {
                     return orient;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenOrientationQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenOrientationQualifier.java
index 85d0c03..a78f217 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenOrientationQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenOrientationQualifier.java
@@ -51,7 +51,7 @@
          * @param value The qualifier value.
          * @return the enum for the qualifier value or null if no matching was found.
          */
-        static ScreenOrientation getEnum(String value) {
+        public static ScreenOrientation getEnum(String value) {
             for (ScreenOrientation orient : values()) {
                 if (orient.mValue.equals(value)) {
                     return orient;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenRatioQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenRatioQualifier.java
index 55857fd..08bce4f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenRatioQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenRatioQualifier.java
@@ -48,7 +48,7 @@
          * @param value The qualifier value.
          * @return the enum for the qualifier value or null if no matching was found.
          */
-        static ScreenRatio getEnum(String value) {
+        public static ScreenRatio getEnum(String value) {
             for (ScreenRatio orient : values()) {
                 if (orient.mValue.equals(value)) {
                     return orient;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenSizeQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenSizeQualifier.java
index d148efc..f48f54d 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenSizeQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/ScreenSizeQualifier.java
@@ -52,7 +52,7 @@
          * @param value The qualifier value.
          * @return the enum for the qualifier value or null if no matching was found.
          */
-        static ScreenSize getEnum(String value) {
+        public static ScreenSize getEnum(String value) {
             for (ScreenSize orient : values()) {
                 if (orient.mValue.equals(value)) {
                     return orient;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/TextInputMethodQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/TextInputMethodQualifier.java
index 6289147..b73776c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/TextInputMethodQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/TextInputMethodQualifier.java
@@ -54,7 +54,7 @@
          * @param value The qualifier value.
          * @return the enum for the qualifier value or null if no matching was found.
          */
-        static TextInputMethod getEnum(String value) {
+        public static TextInputMethod getEnum(String value) {
             for (TextInputMethod orient : values()) {
                 if (orient.mValue.equals(value)) {
                     return orient;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/TouchScreenQualifier.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/TouchScreenQualifier.java
index 758c87f..b3bad48 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/TouchScreenQualifier.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/configurations/TouchScreenQualifier.java
@@ -52,7 +52,7 @@
          * @param value The qualifier value.
          * @return the enum for the qualifier value or null if no matching was found.
          */
-        static TouchScreenType getEnum(String value) {
+        public static TouchScreenType getEnum(String value) {
             for (TouchScreenType orient : values()) {
                 if (orient.mValue.equals(value)) {
                     return orient;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/DeviceConfiguration.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/DeviceConfiguration.java
index e829f93..f483de8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/DeviceConfiguration.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/DeviceConfiguration.java
@@ -17,23 +17,6 @@
 package com.android.ide.eclipse.adt.internal.sdk;
 
 import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
-import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
-import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier.KeyboardState;
-import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier.NavigationMethod;
-import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
-import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
-import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier.ScreenRatio;
-import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier.ScreenSize;
-import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier.TextInputMethod;
-import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier.TouchScreenType;
 
 import java.util.Collections;
 import java.util.HashMap;
@@ -64,66 +47,4 @@
     public Map<String, FolderConfiguration> getConfigs() {
         return mMap;
     }
-
-    /**
-     * temp method returning some hard-coded devices.
-     * TODO: load devices from the SDK and add-ons and remove this method.
-     */
-    public static DeviceConfiguration[] getDevices() {
-        DeviceConfiguration adp1 = new DeviceConfiguration("ADP1");
-        // default config
-        FolderConfiguration defConfig = new FolderConfiguration();
-        defConfig.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL));
-        defConfig.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG));
-        defConfig.addQualifier(new PixelDensityQualifier(Density.MEDIUM));
-        defConfig.addQualifier(new TouchScreenQualifier(TouchScreenType.FINGER));
-        defConfig.addQualifier(new TextInputMethodQualifier(TextInputMethod.QWERTY));
-        defConfig.addQualifier(new NavigationMethodQualifier(NavigationMethod.TRACKBALL));
-        defConfig.addQualifier(new ScreenDimensionQualifier(480, 320));
-
-        // specific configs
-        FolderConfiguration closedLand = new FolderConfiguration();
-        closedLand.set(defConfig);
-        closedLand.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
-        closedLand.addQualifier(new KeyboardStateQualifier(KeyboardState.HIDDEN));
-        adp1.addConfig("Closed, landscape", closedLand);
-
-        FolderConfiguration closedPort = new FolderConfiguration();
-        closedPort.set(defConfig);
-        closedPort.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT));
-        closedPort.addQualifier(new KeyboardStateQualifier(KeyboardState.HIDDEN));
-        adp1.addConfig("Closed, portrait", closedPort);
-
-        FolderConfiguration opened = new FolderConfiguration();
-        opened.set(defConfig);
-        opened.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
-        opened.addQualifier(new KeyboardStateQualifier(KeyboardState.EXPOSED));
-        adp1.addConfig("Opened", opened);
-
-        DeviceConfiguration ion = new DeviceConfiguration("Ion");
-        // default config
-        defConfig = new FolderConfiguration();
-        defConfig.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL));
-        defConfig.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG));
-        defConfig.addQualifier(new PixelDensityQualifier(Density.MEDIUM));
-        defConfig.addQualifier(new TouchScreenQualifier(TouchScreenType.FINGER));
-        defConfig.addQualifier(new KeyboardStateQualifier(KeyboardState.EXPOSED));
-        defConfig.addQualifier(new TextInputMethodQualifier(TextInputMethod.NOKEY));
-        defConfig.addQualifier(new NavigationMethodQualifier(NavigationMethod.TRACKBALL));
-        defConfig.addQualifier(new ScreenDimensionQualifier(480, 320));
-
-        // specific configs
-        FolderConfiguration landscape = new FolderConfiguration();
-        landscape.set(defConfig);
-        landscape.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
-        ion.addConfig("Landscape", landscape);
-
-        FolderConfiguration portrait = new FolderConfiguration();
-        portrait.set(defConfig);
-        portrait.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT));
-        ion.addConfig("Portrait", portrait);
-
-        return new DeviceConfiguration[] { adp1, ion };
-
-    }
-}
+ }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutConfigsXsd.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutConfigsXsd.java
new file mode 100755
index 0000000..ae0bb5b
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutConfigsXsd.java
@@ -0,0 +1,125 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php

+ *

+ * 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.ide.eclipse.adt.internal.sdk;

+

+

+import org.xml.sax.ErrorHandler;

+import org.xml.sax.SAXException;

+

+import java.io.InputStream;

+

+import javax.xml.XMLConstants;

+import javax.xml.transform.stream.StreamSource;

+import javax.xml.validation.Schema;

+import javax.xml.validation.SchemaFactory;

+import javax.xml.validation.Validator;

+

+/**

+ * Public constants for the layout device description XML Schema.

+ */

+public class LayoutConfigsXsd {

+

+    /** The XML namespace of the layout-configs XML. */

+    public static final String NS_LAYOUT_CONFIG_XSD =

+        "http://schemas.android.com/sdk/android/layout-configs/1";                  //$NON-NLS-1$

+

+    /**

+     * The "layout-configs" element is the root element of this schema.

+     *

+     * It must contain one or more "device" elements that each define the configurations

+     * available for a given device.

+     *

+     * These definitions are used in the Graphical Layout Editor in the

+     * Android Development Tools (ADT) plugin for Eclipse.

+     */

+    public static final String NODE_LAYOUT_CONFIGS = "layout-configs";              //$NON-NLS-1$

+

+    /**

+     * A device element must contain at most one "default" element followed

+     * by one or more ""config" elements.

+     *

+     * The "default" element defines all the default parameters inherited

+     * by the following "config" elements. Each "config" element can override

+     * the default values, if any.

+     *

+     * A "device" element also has a required "name" attribute that represents

+     * the user-interface name of this device.

+     */

+    public static final String NODE_DEVICE = "device";                              //$NON-NLS-1$

+

+    /**

+     * The "default" element contains zero or more of all the parameter elements

+     * listed below. It defines all the parameters that are common to all

+     * declared "config" elements.

+     */

+    public static final String NODE_DEFAULT = "default";                            //$NON-NLS-1$

+

+    /**

+     * The "config" element contains zero or more of all the parameter elements

+     * listed below. The parameters from the "default" element (if present) are

+     * automatically inherited and can be overridden.

+     */

+    public static final String NODE_CONFIG = "config";                              //$NON-NLS-1$

+

+

+    public static final String NODE_SCREEN_SIZE = "screen-size";                    //$NON-NLS-1$

+

+    public static final String NODE_SCREEN_RATIO = "screen-ratio";                  //$NON-NLS-1$

+

+    public static final String NODE_SCREEN_ORIENTATION = "screen-orientation";      //$NON-NLS-1$

+

+    public static final String NODE_PIXEL_DENSITY = "pixel-density";                //$NON-NLS-1$

+

+    public static final String NODE_TOUCH_TYPE = "touch-type";                      //$NON-NLS-1$

+

+    public static final String NODE_KEYBOARD_STATE = "keyboard-state";              //$NON-NLS-1$

+

+    public static final String NODE_TEXT_INPUT_METHOD = "text-input-method";        //$NON-NLS-1$

+

+    public static final String NODE_NAV_METHOD = "nav-method";                      //$NON-NLS-1$

+

+    public static final String NODE_SCREEN_DIMENSION = "screen-dimension";          //$NON-NLS-1$

+

+    public static final String NODE_SIZE = "size";                                  //$NON-NLS-1$

+

+    /**

+     * The "name" attribute, used by both the "device" and the "config"

+     * elements. It represents the user-interface name of these objects.

+     */

+    public static final String ATTR_NAME = "name";                                  //$NON-NLS-1$

+

+    /**

+     * Helper to get an input stream of the layout config XML schema.

+     */

+    public static InputStream getXsdStream() {

+        return LayoutConfigsXsd.class.getResourceAsStream("layout-configs.xsd");    //$NON-NLS-1$

+    }

+

+    /** Helper method that returns a {@link Validator} for our XSD */

+    public static Validator getValidator(ErrorHandler handler) throws SAXException {

+        InputStream xsdStream = getXsdStream();

+        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

+        Schema schema = factory.newSchema(new StreamSource(xsdStream));

+        Validator validator = schema.newValidator();

+        if (handler != null) {

+            validator.setErrorHandler(handler);

+        }

+

+        return validator;

+    }

+

+}

diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDeviceHandler.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDeviceHandler.java
new file mode 100644
index 0000000..71d7f18
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutDeviceHandler.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.ide.eclipse.adt.internal.sdk;
+
+import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
+import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier.KeyboardState;
+import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier.NavigationMethod;
+import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier.ScreenRatio;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier.ScreenSize;
+import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier.TextInputMethod;
+import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier.TouchScreenType;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link DefaultHandler} implementation to parse Layout Device XML file.
+ * @see LayoutConfigsXsd
+ * @see Layout-configs.xsd
+ */
+class LayoutDeviceHandler extends DefaultHandler {
+    /*
+     * The handler does most of the work in startElement and endElement.
+     * In startElement, it'll create DeviceConfiguration on <device>, as well as
+     * FolderConfiguration instances on <default> and <config>.
+     * Those objects are then filled as new nodes are discovered.
+     *
+     * For the qualifier values, the qualifier is created and added to the current config
+     * on the endElement, by using the content found in characters().
+     */
+
+    private List<DeviceConfiguration> mDevices = new ArrayList<DeviceConfiguration>();
+
+    private DeviceConfiguration mCurrentDevice;
+    private FolderConfiguration mDefaultConfig;
+    private FolderConfiguration mCurrentConfig;
+    private final StringBuilder mStringAccumulator = new StringBuilder();
+
+    private String mSize1, mSize2;
+
+    public List<DeviceConfiguration> getDevices() {
+        return mDevices;
+    }
+
+    @Override
+    public void startElement(String uri, String localName, String name, Attributes attributes)
+            throws SAXException {
+        if (LayoutConfigsXsd.NODE_DEVICE.equals(localName)) {
+            // get the deviceName, will not be null since we validated the XML.
+            String deviceName = attributes.getValue("", LayoutConfigsXsd.ATTR_NAME);
+
+            // create a device and add it to the list
+            mCurrentDevice = new DeviceConfiguration(deviceName);
+            mDevices.add(mCurrentDevice);
+        } else if (LayoutConfigsXsd.NODE_DEFAULT.equals(localName)) {
+            // create a new default config
+            mDefaultConfig = mCurrentConfig = new FolderConfiguration();
+        } else if (LayoutConfigsXsd.NODE_CONFIG.equals(localName)) {
+            // create a new config
+            mCurrentConfig = new FolderConfiguration();
+
+            // init with default config if applicable
+            if (mDefaultConfig != null) {
+                mCurrentConfig.set(mDefaultConfig);
+            }
+
+            // get the name of the config
+            String deviceName = attributes.getValue("", LayoutConfigsXsd.ATTR_NAME);
+
+            // give it to the current device.
+            mCurrentDevice.addConfig(deviceName, mCurrentConfig);
+        } else if (LayoutConfigsXsd.NODE_SCREEN_DIMENSION.equals(localName)) {
+            mSize1 = mSize2 = null;
+        }
+
+        mStringAccumulator.setLength(0);
+    }
+
+    @Override
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        mStringAccumulator.append(ch, start, length);
+    }
+
+    @Override
+    public void endElement(String uri, String localName, String name) throws SAXException {
+        if (LayoutConfigsXsd.NODE_DEVICE.equals(localName)) {
+            mCurrentDevice = null;
+            mDefaultConfig = null;
+        } else if (LayoutConfigsXsd.NODE_CONFIG.equals(localName)) {
+            mCurrentConfig = null;
+        } else if (LayoutConfigsXsd.NODE_SCREEN_SIZE.equals(localName)) {
+            ScreenSizeQualifier ssq = new ScreenSizeQualifier(
+                    ScreenSize.getEnum(mStringAccumulator.toString()));
+            mCurrentConfig.setScreenSizeQualifier(ssq);
+        } else if (LayoutConfigsXsd.NODE_SCREEN_RATIO.equals(localName)) {
+            ScreenRatioQualifier srq = new ScreenRatioQualifier(
+                    ScreenRatio.getEnum(mStringAccumulator.toString()));
+            mCurrentConfig.setScreenRatioQualifier(srq);
+        } else if (LayoutConfigsXsd.NODE_SCREEN_ORIENTATION.equals(localName)) {
+            ScreenOrientationQualifier soq = new ScreenOrientationQualifier(
+                    ScreenOrientation.getEnum(mStringAccumulator.toString()));
+            mCurrentConfig.setScreenOrientationQualifier(soq);
+        } else if (LayoutConfigsXsd.NODE_PIXEL_DENSITY.equals(localName)) {
+            PixelDensityQualifier pdq = new PixelDensityQualifier(
+                    Density.getEnum(mStringAccumulator.toString()));
+            mCurrentConfig.setPixelDensityQualifier(pdq);
+        } else if (LayoutConfigsXsd.NODE_TOUCH_TYPE.equals(localName)) {
+            TouchScreenQualifier tsq = new TouchScreenQualifier(
+                    TouchScreenType.getEnum(mStringAccumulator.toString()));
+            mCurrentConfig.setTouchTypeQualifier(tsq);
+        } else if (LayoutConfigsXsd.NODE_KEYBOARD_STATE.equals(localName)) {
+            KeyboardStateQualifier ksq = new KeyboardStateQualifier(
+                    KeyboardState.getEnum(mStringAccumulator.toString()));
+            mCurrentConfig.setKeyboardStateQualifier(ksq);
+        } else if (LayoutConfigsXsd.NODE_TEXT_INPUT_METHOD.equals(localName)) {
+            TextInputMethodQualifier timq = new TextInputMethodQualifier(
+                    TextInputMethod.getEnum(mStringAccumulator.toString()));
+            mCurrentConfig.setTextInputMethodQualifier(timq);
+        } else if (LayoutConfigsXsd.NODE_NAV_METHOD.equals(localName)) {
+            NavigationMethodQualifier nmq = new NavigationMethodQualifier(
+                    NavigationMethod.getEnum(mStringAccumulator.toString()));
+            mCurrentConfig.setNavigationMethodQualifier(nmq);
+        } else if (LayoutConfigsXsd.NODE_SCREEN_DIMENSION.equals(localName)) {
+            ScreenDimensionQualifier qual = ScreenDimensionQualifier.getQualifier(mSize1, mSize2);
+            if (qual != null) {
+                mCurrentConfig.setScreenDimensionQualifier(qual);
+            }
+        } else if (LayoutConfigsXsd.NODE_SIZE.equals(localName)) {
+            if (mSize1 == null) {
+                mSize1 = mStringAccumulator.toString();
+            } else if (mSize2 == null) {
+                mSize2 = mStringAccumulator.toString();
+            }
+        }
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
index f93b6c5..4003d88 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java
@@ -19,6 +19,24 @@
 import com.android.ddmlib.IDevice;
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.internal.project.AndroidClasspathContainerInitializer;
+import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
+import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenDimensionQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.KeyboardStateQualifier.KeyboardState;
+import com.android.ide.eclipse.adt.internal.resources.configurations.NavigationMethodQualifier.NavigationMethod;
+import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenOrientationQualifier.ScreenOrientation;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenRatioQualifier.ScreenRatio;
+import com.android.ide.eclipse.adt.internal.resources.configurations.ScreenSizeQualifier.ScreenSize;
+import com.android.ide.eclipse.adt.internal.resources.configurations.TextInputMethodQualifier.TextInputMethod;
+import com.android.ide.eclipse.adt.internal.resources.configurations.TouchScreenQualifier.TouchScreenType;
 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor;
 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor.IProjectListener;
 import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData.LayoutBridge;
@@ -41,15 +59,31 @@
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
 
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Validator;
+
 /**
  * Central point to load, manipulate and deal with the Android SDK. Only one SDK can be used
  * at the same time.
@@ -73,6 +107,8 @@
             new HashMap<IProject, ApkSettings>();
     private final String mDocBaseUrl;
 
+    private List<DeviceConfiguration> mLayoutDevices = new ArrayList<DeviceConfiguration>();
+
     /**
      * Classes implementing this interface will receive notification when targets are changed.
      */
@@ -432,6 +468,9 @@
         // pre-compute some paths
         mDocBaseUrl = getDocumentationBaseUrl(mManager.getLocation() +
                 SdkConstants.OS_SDK_DOCS_FOLDER);
+
+        // create some built-in layout devices
+        createDefaultLayoutDevices();
     }
 
     /**
@@ -518,6 +557,173 @@
         // ignore this. The project will be added to the map the first time the target needs
         // to be resolved.
     }
+
+
+    // ---------- Device Configuration methods ----------
+
+    /**
+     * A SAX error handler that captures the errors and warnings.
+     * This allows us to capture *all* errors and just not get an exception on the first one.
+     */
+    private static class CaptureErrorHandler implements ErrorHandler {
+
+        private final String mSourceLocation;
+
+        private boolean mFoundError = false;
+
+        CaptureErrorHandler(String sourceLocation) {
+            mSourceLocation = sourceLocation;
+        }
+
+        public boolean foundError() {
+            return mFoundError;
+        }
+
+        /**
+         * @throws SAXException
+         */
+        public void error(SAXParseException ex) throws SAXException {
+            mFoundError = true;
+            AdtPlugin.log(ex, "Error validating %1$s", mSourceLocation);
+        }
+
+        /**
+         * @throws SAXException
+         */
+        public void fatalError(SAXParseException ex) throws SAXException {
+            mFoundError = true;
+            AdtPlugin.log(ex, "Error validating %1$s", mSourceLocation);
+        }
+
+        /**
+         * @throws SAXException
+         */
+        public void warning(SAXParseException ex) throws SAXException {
+            // ignore those for now.
+        }
+    }
+
+    /**
+     * Returns the list of {@link DeviceConfiguration} found in the SDK.
+     */
+    public List<DeviceConfiguration> getLayoutDevices() {
+        return mLayoutDevices;
+    }
+
+    /**
+     * Parses the SDK add-ons to look for files called {@link SdkConstants#FN_DEVICES_XML} to
+     * load {@link DeviceConfiguration} from them.
+     */
+    public void parseAddOnLayoutDevices() {
+        SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+        parserFactory.setNamespaceAware(true);
+
+        IAndroidTarget[] targets = mManager.getTargets();
+        for (IAndroidTarget target : targets) {
+            if (target.isPlatform() == false) {
+                File deviceXml = new File(target.getLocation(), SdkConstants.FN_DEVICES_XML);
+                if (deviceXml.isFile()) {
+                    parseLayoutDevices(parserFactory, deviceXml);
+                }
+            }
+        }
+
+        mLayoutDevices = Collections.unmodifiableList(mLayoutDevices);
+    }
+
+    /**
+     * Does the actual parsing of a devices.xml file.
+     */
+    private void parseLayoutDevices(SAXParserFactory parserFactory, File deviceXml) {
+        // first we validate the XML
+        try {
+            Source source = new StreamSource(new FileReader(deviceXml));
+
+            CaptureErrorHandler errorHandler = new CaptureErrorHandler(deviceXml.getAbsolutePath());
+
+            Validator validator = LayoutConfigsXsd.getValidator(errorHandler);
+            validator.validate(source);
+
+            if (errorHandler.foundError() == false) {
+                // do the actual parsing
+                LayoutDeviceHandler handler = new LayoutDeviceHandler();
+
+                SAXParser parser = parserFactory.newSAXParser();
+                parser.parse(new InputSource(new FileInputStream(deviceXml)), handler);
+
+                // get the parsed devices
+                mLayoutDevices.addAll(handler.getDevices());
+            }
+        } catch (SAXException e) {
+            AdtPlugin.log(e, "Error parsing %1$s", deviceXml.getAbsoluteFile());
+        } catch (FileNotFoundException e) {
+            // this shouldn't happen as we check above.
+        } catch (IOException e) {
+            AdtPlugin.log(e, "Error reading %1$s", deviceXml.getAbsoluteFile());
+        } catch (ParserConfigurationException e) {
+            AdtPlugin.log(e, "Error parsing %1$s", deviceXml.getAbsoluteFile());
+        }
+    }
+
+    /**
+     * Creates some built-it layout devices.
+     */
+    private void createDefaultLayoutDevices() {
+        DeviceConfiguration adp1 = new DeviceConfiguration("ADP1");
+        mLayoutDevices.add(adp1);
+        // default config
+        FolderConfiguration defConfig = new FolderConfiguration();
+        defConfig.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL));
+        defConfig.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG));
+        defConfig.addQualifier(new PixelDensityQualifier(Density.MEDIUM));
+        defConfig.addQualifier(new TouchScreenQualifier(TouchScreenType.FINGER));
+        defConfig.addQualifier(new KeyboardStateQualifier(KeyboardState.SOFT));
+        defConfig.addQualifier(new TextInputMethodQualifier(TextInputMethod.QWERTY));
+        defConfig.addQualifier(new NavigationMethodQualifier(NavigationMethod.TRACKBALL));
+        defConfig.addQualifier(new ScreenDimensionQualifier(480, 320));
+
+        // specific configs
+        FolderConfiguration closedPort = new FolderConfiguration();
+        closedPort.set(defConfig);
+        closedPort.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT));
+        adp1.addConfig("Portrait, closed", closedPort);
+
+        FolderConfiguration closedLand = new FolderConfiguration();
+        closedLand.set(defConfig);
+        closedLand.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
+        adp1.addConfig("Landscape, closed", closedLand);
+
+        FolderConfiguration opened = new FolderConfiguration();
+        opened.set(defConfig);
+        opened.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
+        opened.addQualifier(new KeyboardStateQualifier(KeyboardState.EXPOSED));
+        adp1.addConfig("Landscape, opened", opened);
+
+        DeviceConfiguration ion = new DeviceConfiguration("Ion");
+        mLayoutDevices.add(ion);
+        // default config
+        defConfig = new FolderConfiguration();
+        defConfig.addQualifier(new ScreenSizeQualifier(ScreenSize.NORMAL));
+        defConfig.addQualifier(new ScreenRatioQualifier(ScreenRatio.NOTLONG));
+        defConfig.addQualifier(new PixelDensityQualifier(Density.MEDIUM));
+        defConfig.addQualifier(new TouchScreenQualifier(TouchScreenType.FINGER));
+        defConfig.addQualifier(new KeyboardStateQualifier(KeyboardState.EXPOSED));
+        defConfig.addQualifier(new TextInputMethodQualifier(TextInputMethod.NOKEY));
+        defConfig.addQualifier(new NavigationMethodQualifier(NavigationMethod.TRACKBALL));
+        defConfig.addQualifier(new ScreenDimensionQualifier(480, 320));
+
+        // specific configs
+        FolderConfiguration landscape = new FolderConfiguration();
+        landscape.set(defConfig);
+        landscape.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.LANDSCAPE));
+        ion.addConfig("Landscape", landscape);
+
+        FolderConfiguration portrait = new FolderConfiguration();
+        portrait.set(defConfig);
+        portrait.addQualifier(new ScreenOrientationQualifier(ScreenOrientation.PORTRAIT));
+        ion.addConfig("Portrait", portrait);
+    }
 }
 
 
+
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/layout-configs.xsd b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/layout-configs.xsd
new file mode 100755
index 0000000..476fce7
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/layout-configs.xsd
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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.
+-->
+<xsd:schema
+    targetNamespace="http://schemas.android.com/sdk/android/layout-configs/1"
+    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+    xmlns:c="http://schemas.android.com/sdk/android/layout-configs/1"
+    elementFormDefault="qualified"
+    attributeFormDefault="unqualified"
+    version="1">
+
+    <xsd:element name="layout-configs">
+        <xsd:annotation>
+            <xsd:documentation>
+                The "layout-configs" element is the root element of this schema.
+
+                It must contain one or more "device" elements that each define the configurations
+                available for a given device.
+
+                These definitions are used in the Graphical Layout Editor in the
+                Android Development Tools (ADT) plugin for Eclipse.
+            </xsd:documentation>
+        </xsd:annotation>
+
+        <xsd:complexType>
+            <xsd:sequence>
+                <!-- layout-configs defines a sequence of 1..n device elements. -->
+                <xsd:element name="device" minOccurs="1" maxOccurs="unbounded">
+
+                    <xsd:annotation>
+                        <xsd:documentation>
+                            A device element must contain at most one "default" element
+                            followed by one or more "config" elements.
+
+                            The "default" element defines all the default parameters
+                            inherited by the following "config" elements.
+                            Each "config" element can override the default values, if any.
+
+                            A "device" element also has a required "name" attribute that
+                            represents the user-interface name of this device.
+                        </xsd:documentation>
+                    </xsd:annotation>
+
+                    <xsd:complexType>
+                        <!-- device defines a choice of 0..1 default element
+                        and 1..n config elements. -->
+
+                        <xsd:sequence>
+                            <xsd:element name="default" type="c:parametersType"
+                                         minOccurs="0"  maxOccurs="1" />
+                            <xsd:element name="config"  type="c:configType"
+                                         minOccurs="1"  maxOccurs="unbounded" />
+                        </xsd:sequence>
+
+                        <xsd:attribute name="name" type="xsd:normalizedString" use="required" />
+                    </xsd:complexType>
+
+                </xsd:element>
+            </xsd:sequence>
+        </xsd:complexType>
+    </xsd:element>
+
+    <!-- The type of a device>default element.
+         This is overridden by configType below for the device>config element.
+    -->
+    <xsd:complexType name="parametersType">
+        <xsd:annotation>
+            <xsd:documentation>
+                The parametersType define all the parameters that can happen either in a
+                "default" element or in a named "config" element.
+                Each parameter element can appear once at most.
+            </xsd:documentation>
+        </xsd:annotation>
+
+        <xsd:all>
+            <!-- parametersType says that 0..1 of each of these elements must be declared. -->
+
+            <xsd:element name="screen-size" minOccurs="0">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                        <xsd:enumeration value="small" />
+                        <xsd:enumeration value="normal" />
+                        <xsd:enumeration value="large" />
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
+
+            <xsd:element name="screen-ratio" minOccurs="0">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                        <xsd:enumeration value="long" />
+                        <xsd:enumeration value="notlong" />
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
+
+            <xsd:element name="screen-orientation" minOccurs="0">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                        <xsd:enumeration value="port" />
+                        <xsd:enumeration value="land" />
+                        <xsd:enumeration value="square" />
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
+
+            <xsd:element name="pixel-density" minOccurs="0">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                        <xsd:enumeration value="ldpi" />
+                        <xsd:enumeration value="mdpi" />
+                        <xsd:enumeration value="hdpi" />
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
+
+            <xsd:element name="touch-type" minOccurs="0">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                        <xsd:enumeration value="notouch" />
+                        <xsd:enumeration value="stylus" />
+                        <xsd:enumeration value="finger" />
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
+
+            <xsd:element name="keyboard-state" minOccurs="0">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                        <xsd:enumeration value="keysexposed" />
+                        <xsd:enumeration value="keyshidden" />
+                        <xsd:enumeration value="keyssoft" />
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
+
+            <xsd:element name="text-input-method" minOccurs="0">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                        <xsd:enumeration value="nokeys" />
+                        <xsd:enumeration value="qwerty" />
+                        <xsd:enumeration value="12key" />
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
+
+            <xsd:element name="nav-method" minOccurs="0">
+                <xsd:simpleType>
+                    <xsd:restriction base="xsd:token">
+                        <xsd:enumeration value="dpad" />
+                        <xsd:enumeration value="trackball" />
+                        <xsd:enumeration value="wheel" />
+                        <xsd:enumeration value="nonav" />
+                    </xsd:restriction>
+                </xsd:simpleType>
+            </xsd:element>
+
+            <xsd:element name="screen-dimension" minOccurs="0">
+                <xsd:complexType>
+                    <xsd:sequence minOccurs="2" maxOccurs="2">
+
+                        <xsd:element name="size">
+                            <xsd:simpleType>
+                                <xsd:restriction base="xsd:positiveInteger" />
+                            </xsd:simpleType>
+                        </xsd:element>
+
+                    </xsd:sequence>
+                </xsd:complexType>
+            </xsd:element>
+        </xsd:all>
+    </xsd:complexType>
+
+    <!-- The type definition of a device>config element.
+         This type is basically all the element defined by parametersType and an extra
+         required "name" attribute for the user-interface configuration name.
+    -->
+    <xsd:complexType name="configType">
+        <xsd:annotation>
+            <xsd:documentation>
+                The configType defines the content of a "config" element in a "device" element.
+
+                A "config" element can have all the parameters elements defined by
+                "parameterType". It also has a required "name" attribute that indicates the
+                user-interface name for this configuration.
+            </xsd:documentation>
+        </xsd:annotation>
+
+        <xsd:complexContent>
+            <xsd:extension base="c:parametersType">
+                <xsd:attribute name="name" type="xsd:normalizedString" use="required" />
+            </xsd:extension>
+        </xsd:complexContent>
+    </xsd:complexType>
+
+</xsd:schema>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/sdk/TestLayoutConfisXsd.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/sdk/TestLayoutConfisXsd.java
new file mode 100755
index 0000000..45332f2
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/sdk/TestLayoutConfisXsd.java
@@ -0,0 +1,287 @@
+/*

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php

+ *

+ * 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.ide.eclipse.adt.internal.sdk;

+

+import org.xml.sax.ErrorHandler;

+import org.xml.sax.SAXException;

+import org.xml.sax.SAXParseException;

+

+import java.io.InputStream;

+import java.io.StringReader;

+

+import javax.xml.transform.Source;

+import javax.xml.transform.stream.StreamSource;

+import javax.xml.validation.Validator;

+

+import junit.framework.TestCase;

+

+/**

+ * Tests local validation of a Layout-Configs sample XMLs using an XML Schema validator.

+ */

+public class TestLayoutConfisXsd extends TestCase {

+

+    @Override

+    protected void setUp() throws Exception {

+        super.setUp();

+    }

+

+    @Override

+    protected void tearDown() throws Exception {

+        super.tearDown();

+    }

+

+    /**

+     * A SAX error handler that captures the errors and warnings.

+     * This allows us to capture *all* errors and just not get an exception on the first one.

+     */

+    private static class CaptureErrorHandler implements ErrorHandler {

+

+        private String mWarnings = "";

+        private String mErrors = "";

+

+        @SuppressWarnings("unused")

+        public String getErrors() {

+            return mErrors;

+        }

+

+        @SuppressWarnings("unused")

+        public String getWarnings() {

+            return mWarnings;

+        }

+

+        /**

+         * Verifies if the handler captures some errors or warnings.

+         * Prints them on stderr.

+         * Also fails the unit test if any error was generated.

+         */

+        public void verify() {

+            if (mWarnings.length() > 0) {

+                System.err.println(mWarnings);

+            }

+

+            if (mErrors.length() > 0) {

+                System.err.println(mErrors);

+                fail(mErrors);

+            }

+        }

+

+        /**

+         * @throws SAXException

+         */

+        public void error(SAXParseException ex) throws SAXException {

+            mErrors += "Error: " + ex.getMessage() + "\n";

+        }

+

+        /**

+         * @throws SAXException

+         */

+        public void fatalError(SAXParseException ex) throws SAXException {

+            mErrors += "Fatal Error: " + ex.getMessage() + "\n";

+        }

+

+        /**

+         * @throws SAXException

+         */

+        public void warning(SAXParseException ex) throws SAXException {

+            mWarnings += "Warning: " + ex.getMessage() + "\n";

+        }

+

+    }

+

+    // --- Helpers ------------

+

+    /** Validate a valid sample using an InputStream */

+    public void testValidateLocalRepositoryFile() throws Exception {

+

+        InputStream xmlStream =

+            TestLayoutConfisXsd.class.getResourceAsStream("config_sample.xml");

+        Source source = new StreamSource(xmlStream);

+

+        CaptureErrorHandler handler = new CaptureErrorHandler();

+        Validator validator = LayoutConfigsXsd.getValidator(handler);

+        validator.validate(source);

+        handler.verify();

+    }

+

+    /** An helper that validates a string against an expected regexp. */

+    private void assertRegex(String expectedRegexp, String actualString) {

+        assertNotNull(actualString);

+        assertTrue(

+                String.format("Regexp Assertion Failed:\nExpected: %s\nActual: %s\n",

+                        expectedRegexp, actualString),

+                actualString.matches(expectedRegexp));

+    }

+

+    // --- Tests ------------

+

+    /** A document should at least have a root to be valid */

+    public void testEmptyXml() throws Exception {

+        String document = "<?xml version=\"1.0\"?>";

+

+        Source source = new StreamSource(new StringReader(document));

+

+        CaptureErrorHandler handler = new CaptureErrorHandler();

+        Validator validator = LayoutConfigsXsd.getValidator(handler);

+

+        try {

+            validator.validate(source);

+        } catch (SAXParseException e) {

+            // We expect to get this specific exception message

+            assertRegex("Premature end of file.*", e.getMessage());

+            return;

+        }

+        // We shouldn't get here

+        handler.verify();

+        fail();

+    }

+

+    /** A document with an unknown element. */

+    public void testUnknownContentXml() throws Exception {

+        String document = "<?xml version=\"1.0\"?>" +

+            "<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +

+            "<d:unknown />" +

+            "</d:layout-configs>";

+

+        Source source = new StreamSource(new StringReader(document));

+

+        // don't capture the validator errors, we want it to fail and catch the exception

+        Validator validator = LayoutConfigsXsd.getValidator(null);

+        try {

+            validator.validate(source);

+        } catch (SAXParseException e) {

+            // We expect a parse expression referring to this grammar rule

+            assertRegex("cvc-complex-type.2.4.a: Invalid content was found.*", e.getMessage());

+            return;

+        }

+        // If we get here, the validator has not failed as we expected it to.

+        fail();

+    }

+

+    /** A document with an missing attribute in a device element. */

+    public void testIncompleteContentXml() throws Exception {

+        String document = "<?xml version=\"1.0\"?>" +

+            "<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +

+            "<d:device />" +

+            "</d:layout-configs>";

+

+        Source source = new StreamSource(new StringReader(document));

+

+        // don't capture the validator errors, we want it to fail and catch the exception

+        Validator validator = LayoutConfigsXsd.getValidator(null);

+        try {

+            validator.validate(source);

+        } catch (SAXParseException e) {

+            // We expect a parse error referring to this grammar rule

+            assertRegex("cvc-complex-type.4: Attribute 'name' must appear on element 'd:device'.", e.getMessage());

+            return;

+        }

+        // If we get here, the validator has not failed as we expected it to.

+        fail();

+    }

+

+    /** A document with a root element containing no device element is not valid. */

+    public void testEmptyRootXml() throws Exception {

+        String document = "<?xml version=\"1.0\"?>" +

+            "<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" />";

+

+        Source source = new StreamSource(new StringReader(document));

+

+        // don't capture the validator errors, we want it to fail and catch the exception

+        Validator validator = LayoutConfigsXsd.getValidator(null);

+        try {

+            validator.validate(source);

+        } catch (SAXParseException e) {

+            // We expect a parse expression referring to this grammar rule

+            assertRegex("cvc-complex-type.2.4.b: The content of element 'd:layout-configs' is not complete.*", e.getMessage());

+            return;

+        }

+        // If we get here, the validator has not failed as we expected it to.

+        fail();

+    }

+

+    /** A document with an empty device element is not valid. */

+    public void testEmptyDeviceXml() throws Exception {

+        String document = "<?xml version=\"1.0\"?>" +

+            "<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +

+            "<d:device name=\"foo\"/>" +

+            "</d:layout-configs>";

+

+        Source source = new StreamSource(new StringReader(document));

+

+        // don't capture the validator errors, we want it to fail and catch the exception

+        Validator validator = LayoutConfigsXsd.getValidator(null);

+        try {

+            validator.validate(source);

+        } catch (SAXParseException e) {

+            // We expect a parse error referring to this grammar rule

+            assertRegex("cvc-complex-type.2.4.b: The content of element 'd:device' is not complete.*", e.getMessage());

+            return;

+        }

+        // If we get here, the validator has not failed as we expected it to.

+        fail();

+    }

+

+    /** A document with two default elements in a device element is not valid. */

+    public void testTwoDefaultsXml() throws Exception {

+        String document = "<?xml version=\"1.0\"?>" +

+            "<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +

+            "<d:device name=\"foo\">" +

+            "  <d:default />" +

+            "  <d:default />" +

+            "</d:device>" +

+            "</d:layout-configs>";

+

+        Source source = new StreamSource(new StringReader(document));

+

+        // don't capture the validator errors, we want it to fail and catch the exception

+        Validator validator = LayoutConfigsXsd.getValidator(null);

+        try {

+            validator.validate(source);

+        } catch (SAXParseException e) {

+            // We expect a parse error referring to this grammar rule

+            assertRegex("cvc-complex-type.2.4.a: Invalid content was found starting with element 'd:default'.*", e.getMessage());

+            return;

+        }

+        // If we get here, the validator has not failed as we expected it to.

+        fail();

+    }

+

+    /** The default elements must be defined before the config one. It's invalid if after. */

+    public void testDefaultConfigOrderXml() throws Exception {

+        String document = "<?xml version=\"1.0\"?>" +

+            "<d:layout-configs xmlns:d=\"http://schemas.android.com/sdk/android/layout-configs/1\" >" +

+            "<d:device name=\"foo\">" +

+            "  <d:config name=\"must-be-after-default\" />" +

+            "  <d:default />" +

+            "</d:device>" +

+            "</d:layout-configs>";

+

+        Source source = new StreamSource(new StringReader(document));

+

+        // don't capture the validator errors, we want it to fail and catch the exception

+        Validator validator = LayoutConfigsXsd.getValidator(null);

+        try {

+            validator.validate(source);

+        } catch (SAXParseException e) {

+            // We expect a parse error referring to this grammar rule

+            assertRegex("cvc-complex-type.2.4.a: Invalid content was found starting with element 'd:default'.*", e.getMessage());

+            return;

+        }

+        // If we get here, the validator has not failed as we expected it to.

+        fail();

+    }

+}

diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/sdk/config_sample.xml b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/sdk/config_sample.xml
new file mode 100755
index 0000000..12c481d
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/sdk/config_sample.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0"?>

+<!--

+ * Copyright (C) 2009 The Android Open Source Project

+ *

+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php

+ *

+ * 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.

+-->

+<d:layout-configs

+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

+    xmlns:d="http://schemas.android.com/sdk/android/layout-configs/1">

+

+    <d:device name="MyDevice">        <!-- 1..n -->

+        <d:default>                   <!-- 0..1 -->

+            <d:screen-size>small</d:screen-size>

+            <d:screen-ratio>long</d:screen-ratio>

+            <d:screen-orientation>port</d:screen-orientation>

+            <d:pixel-density>ldpi</d:pixel-density>

+            <d:touch-type>notouch</d:touch-type>

+            <d:keyboard-state>keysexposed</d:keyboard-state>

+            <d:text-input-method>nokeys</d:text-input-method>

+            <d:nav-method>dpad</d:nav-method>

+            <d:screen-dimension>

+                <d:size>240</d:size>    <!-- 2 * int>0 -->

+                <d:size>480</d:size>

+            </d:screen-dimension>

+        </d:default>

+

+        <d:config name="Portrait">

+            <d:keyboard-state>keyshidden</d:keyboard-state>

+            <d:screen-orientation>port</d:screen-orientation>

+        </d:config>

+        <d:config name="Landscape, closed">

+            <d:keyboard-state>keyshidden</d:keyboard-state>

+            <d:screen-orientation>land</d:screen-orientation>

+        </d:config>

+        <d:config name="Landscape, open">

+            <d:keyboard-state>keysexposed</d:keyboard-state>

+            <d:screen-orientation>land</d:screen-orientation>

+        </d:config>

+

+        <d:config name="screen-size-small">

+            <d:screen-size>small</d:screen-size>

+        </d:config>

+        <d:config name="screen-size-normal">

+            <d:screen-size>normal</d:screen-size>

+        </d:config>

+        <d:config name="screen-size-large">

+            <d:screen-size>large</d:screen-size>

+        </d:config>

+

+        <d:config name="screen-ratio-long">

+            <d:screen-ratio>long</d:screen-ratio>

+        </d:config>

+        <d:config name="screen-ratio-notlong">

+            <d:screen-ratio>notlong</d:screen-ratio>

+        </d:config>

+

+        <d:config name="screen-orientation-port">

+            <d:screen-orientation>port</d:screen-orientation>

+        </d:config>

+        <d:config name="screen-orientation-land">

+            <d:screen-orientation>land</d:screen-orientation>

+        </d:config>

+        <d:config name="screen-orientation-square">

+            <d:screen-orientation>square</d:screen-orientation>

+        </d:config>

+

+        <d:config name="pixel-density-ldpi">

+            <d:pixel-density>ldpi</d:pixel-density>

+        </d:config>

+        <d:config name="pixel-density-mdpi">

+            <d:pixel-density>mdpi</d:pixel-density>

+        </d:config>

+        <d:config name="pixel-density-hdpi">

+            <d:pixel-density>hdpi</d:pixel-density>

+        </d:config>

+

+        <d:config name="touch-type-notouch">

+            <d:touch-type>notouch</d:touch-type>

+        </d:config>

+        <d:config name="touch-type-stylus">

+            <d:touch-type>stylus</d:touch-type>

+        </d:config>

+        <d:config name="touch-type-finger">

+            <d:touch-type>finger</d:touch-type>

+        </d:config>

+

+        <d:config name="text-input-method-nokeys">

+            <d:text-input-method>nokeys</d:text-input-method>

+        </d:config>

+        <d:config name="text-input-method-qwerty">

+            <d:text-input-method>qwerty</d:text-input-method>

+        </d:config>

+        <d:config name="text-input-method-12key">

+            <d:text-input-method>12key</d:text-input-method>

+        </d:config>

+

+        <d:config name="nav-method-dpad">

+            <d:nav-method>dpad</d:nav-method>

+        </d:config>

+        <d:config name="nav-method-trackball">

+            <d:nav-method>trackball</d:nav-method>

+        </d:config>

+        <d:config name="nav-method-wheel">

+            <d:nav-method>wheel</d:nav-method>

+        </d:config>

+        <d:config name="nav-method-nonav">

+            <d:nav-method>nonav</d:nav-method>

+        </d:config>

+

+    </d:device>

+

+

+    <d:device name="SomePhone">       <!-- 1..n -->

+        <d:config name="screen-size-normal">

+            <d:screen-size>normal</d:screen-size>

+        </d:config>

+    </d:device>

+

+</d:layout-configs>

diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/resources/configurations/PixelDensityQualifierTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/resources/configurations/PixelDensityQualifierTest.java
index 23107a1..658d4d2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/resources/configurations/PixelDensityQualifierTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/resources/configurations/PixelDensityQualifierTest.java
@@ -18,6 +18,7 @@
 
 import com.android.ide.eclipse.adt.internal.resources.configurations.FolderConfiguration;
 import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier;
+import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
 
 import junit.framework.TestCase;
 
@@ -41,16 +42,16 @@
     }
 
     public void testCheckAndSet() {
-        assertEquals(true, pdq.checkAndSet("123dpi", config));//$NON-NLS-1$
+        assertEquals(true, pdq.checkAndSet("ldpi", config));//$NON-NLS-1$
         assertTrue(config.getPixelDensityQualifier() != null);
-        assertEquals(123, config.getPixelDensityQualifier().getValue());
-        assertEquals("123dpi", config.getPixelDensityQualifier().toString()); //$NON-NLS-1$
+        assertEquals(Density.LOW, config.getPixelDensityQualifier().getValue());
+        assertEquals("ldpi", config.getPixelDensityQualifier().toString()); //$NON-NLS-1$
     }
 
     public void testFailures() {
         assertEquals(false, pdq.checkAndSet("", config));//$NON-NLS-1$
         assertEquals(false, pdq.checkAndSet("dpi", config));//$NON-NLS-1$
-        assertEquals(false, pdq.checkAndSet("123DPI", config));//$NON-NLS-1$
+        assertEquals(false, pdq.checkAndSet("123dpi", config));//$NON-NLS-1$
         assertEquals(false, pdq.checkAndSet("123", config));//$NON-NLS-1$
         assertEquals(false, pdq.checkAndSet("sdfdpi", config));//$NON-NLS-1$
     }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/resources/manager/ConfigMatchTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/resources/manager/ConfigMatchTest.java
index 7601648..c0533ed 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/resources/manager/ConfigMatchTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/resources/manager/ConfigMatchTest.java
@@ -88,13 +88,16 @@
                 null, // network code
                 null, // language
                 null, // region
+                null, // screen size
+                null, // screen ratio
                 null, // screen orientation
                 null, // dpi
                 null, // touch mode
                 null, // keyboard state
                 null, // text input
                 null, // navigation
-                null); // screen size
+                null, // screen dimension
+                null);// version
 
         addFolder(mResources, defaultConfig, validMemberList);
 
@@ -103,13 +106,16 @@
                 null, // network code
                 "en", // language
                 null, // region
+                null, // screen size
+                null, // screen ratio
                 null, // screen orientation
                 null, // dpi
                 null, // touch mode
                 KeyboardState.EXPOSED.getValue(), // keyboard state
                 null, // text input
                 null, // navigation
-                null); // screen size
+                null, // screen dimension
+                null);// version
 
         addFolder(mResources, config1, validMemberList);
 
@@ -118,13 +124,16 @@
                 null, // network code
                 "en", // language
                 null, // region
+                null, // screen size
+                null, // screen ratio
                 null, // screen orientation
                 null, // dpi
                 null, // touch mode
                 KeyboardState.HIDDEN.getValue(), // keyboard state
                 null, // text input
                 null, // navigation
-                null); // screen size
+                null, // screen dimension
+                null);// version
 
         addFolder(mResources, config2, validMemberList);
 
@@ -133,13 +142,16 @@
                 null, // network code
                 "en", // language
                 null, // region
+                null, // screen size
+                null, // screen ratio
                 ScreenOrientation.LANDSCAPE.getValue(), // screen orientation
                 null, // dpi
                 null, // touch mode
                 null, // keyboard state
                 null, // text input
                 null, // navigation
-                null); // screen size
+                null, // screen dimension
+                null);// version
 
         addFolder(mResources, config3, validMemberList);
 
@@ -148,13 +160,16 @@
                 "mnc435", // network code
                 "en", // language
                 "rUS", // region
+                "normal", // screen size
+                "notlong", // screen ratio
                 ScreenOrientation.LANDSCAPE.getValue(), // screen orientation
-                "160dpi", // dpi
+                "mdpi", // dpi
                 TouchScreenType.FINGER.getValue(), // touch mode
                 KeyboardState.EXPOSED.getValue(), // keyboard state
                 TextInputMethod.QWERTY.getValue(), // text input
                 NavigationMethod.DPAD.getValue(), // navigation
-                "480x320"); // screen size
+                "480x320", // screen dimension
+                "v3"); // version
 
         addFolder(mResources, config4, invalidMemberList);
     }
@@ -171,13 +186,16 @@
                 "mnc435", // network code
                 "en", // language
                 "rUS", // region
+                "normal", // screen size
+                "notlong", // screen ratio
                 ScreenOrientation.LANDSCAPE.getValue(), // screen orientation
-                "160dpi", // dpi
+                "mdpi", // dpi
                 TouchScreenType.FINGER.getValue(), // touch mode
                 KeyboardState.EXPOSED.getValue(), // keyboard state
                 TextInputMethod.QWERTY.getValue(), // text input
                 NavigationMethod.DPAD.getValue(), // navigation
-                "480x320"); // screen size
+                "480x320", // screen dimension
+                "v3"); // version
 
         ResourceFile result = mResources.getMatchingFile(SEARCHED_FILENAME,
                 ResourceFolderType.LAYOUT, testConfig);
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
index 4ef3468..b276ae3 100644
--- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
@@ -78,6 +78,8 @@
     public final static String FN_PLUGIN_PROP = "plugin.prop";
     /** add-on manifest file */
     public final static String FN_MANIFEST_INI = "manifest.ini";
+    /** add-on layout device XML file. */
+    public final static String FN_DEVICES_XML = "devices.xml";
     /** hardware properties definition file */
     public final static String FN_HARDWARE_INI = "hardware-properties.ini";