Merge change 27217 into eclair
* changes:
XML Schema for layout configurations.
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..871020c
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/LayoutConfigsXsd.java
@@ -0,0 +1,103 @@
+/*
+ * 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 java.io.InputStream;
+
+/**
+ * Public constants for the sdk-repository 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$
+ }
+
+}
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..e045229
--- /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="medium" />
+ <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..f4ad1bb
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/sdk/TestLayoutConfisXsd.java
@@ -0,0 +1,303 @@
+/*
+ * 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.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+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 ------------
+
+ /** Helper method that returns a validator for our XSD */
+ private Validator getValidator(CaptureErrorHandler handler) throws SAXException {
+ InputStream xsdStream = LayoutConfigsXsd.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;
+ }
+
+ /** 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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..29f48cd
--- /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-medium">
+ <d:screen-size>medium</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-medium">
+ <d:screen-size>medium</d:screen-size>
+ </d:config>
+ </d:device>
+
+</d:layout-configs>