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";