aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/product_sdk.mk2
-rw-r--r--build/sdk_only_whitelist.mk1
-rw-r--r--build/tools.atree9
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/AbstractBufferFindTarget.java117
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/FindDialog.java124
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/IFindTarget.java21
-rw-r--r--ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java63
-rw-r--r--ddms/libs/ddmuilib/tests/src/com/android/ddmuilib/logcat/RollingBufferFindTest.java108
-rw-r--r--device_validator/Android.mk5
-rw-r--r--device_validator/MODULE_LICENSE_APACHE20
-rw-r--r--device_validator/app/.classpath7
-rw-r--r--device_validator/app/.project17
-rw-r--r--device_validator/app/.settings/org.eclipse.jdt.ui.prefs3
-rw-r--r--device_validator/app/Android.mk31
-rw-r--r--device_validator/app/etc/Android.mk10
-rw-r--r--device_validator/app/etc/README19
-rwxr-xr-xdevice_validator/app/etc/device_validator79
-rw-r--r--device_validator/app/etc/manifest.txt3
-rw-r--r--device_validator/app/src/com/android/validator/DeviceValidator.java55
-rw-r--r--device_validator/dvlib/.classpath8
-rw-r--r--device_validator/dvlib/.gitignore1
-rw-r--r--device_validator/dvlib/.project17
-rw-r--r--device_validator/dvlib/Android.mk26
-rw-r--r--device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java344
-rw-r--r--device_validator/dvlib/src/com/android/dvlib/devices.xsd884
-rw-r--r--device_validator/dvlib/tests/Android.mk30
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/DeviceSchemaTest.java311
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices.xml290
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml155
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml134
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml80
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_no_software.xml80
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml128
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml140
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/extras/frame.jpeg0
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/extras/frame.png0
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/extras/sixteen.jpeg0
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/extras/sixteen.png0
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/extras/sixtyfour.jpeg0
-rw-r--r--device_validator/dvlib/tests/src/com/android/dvlib/extras/sixtyfour.png0
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseViewRule.java6
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptParser.java32
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java21
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/common/CommonXmlEditor.java1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinter.java32
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java72
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java45
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java13
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java69
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java4
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java22
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java7
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java388
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java38
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java36
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java14
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java278
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/UpdateToolsPage.java94
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/messages.properties2
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java8
-rwxr-xr-xeclipse/plugins/com.android.ide.eclipse.gldebugger/.classpath1
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java111
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorActionBarAdvisor.java8
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinterTest.java28
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidatorTest.java26
-rw-r--r--emulator/opengl/host/tools/emugen/ApiGen.cpp13
-rw-r--r--emulator/opengl/system/egl/Android.mk2
-rw-r--r--emulator/opengl/tests/gles_android_wrapper/Android.mk4
-rw-r--r--emulator/opengl/tests/translator_tests/GLES_CM/Android.mk9
-rw-r--r--emulator/opengl/tests/translator_tests/GLES_V2/Android.mk7
-rw-r--r--rule_api/src/com/android/ide/common/api/IClientRulesEngine.java22
-rw-r--r--templates/activities/BlankActivity/globals.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/globals.xml.ftl)0
-rw-r--r--templates/activities/BlankActivity/recipe.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/recipe.xml.ftl)0
-rw-r--r--templates/activities/BlankActivity/root/AndroidManifest.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/AndroidManifest.xml.ftl)0
-rw-r--r--templates/activities/BlankActivity/root/res/drawable-hdpi/ic_action_search.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-hdpi/ic_action_search.png)bin3120 -> 3120 bytes
-rw-r--r--templates/activities/BlankActivity/root/res/drawable-mdpi/ic_action_search.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-mdpi/ic_action_search.png)bin3030 -> 3030 bytes
-rw-r--r--templates/activities/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png)bin3199 -> 3199 bytes
-rw-r--r--templates/activities/BlankActivity/root/res/layout/activity_fragment_container.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_fragment_container.xml)0
-rw-r--r--templates/activities/BlankActivity/root/res/layout/activity_pager.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_pager.xml.ftl)0
-rw-r--r--templates/activities/BlankActivity/root/res/layout/activity_simple.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_simple.xml)0
-rw-r--r--templates/activities/BlankActivity/root/res/menu/main.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/menu/main.xml)0
-rw-r--r--templates/activities/BlankActivity/root/res/values-large/dimens.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values-large/dimens.xml)0
-rw-r--r--templates/activities/BlankActivity/root/res/values/dimens.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/dimens.xml)0
-rw-r--r--templates/activities/BlankActivity/root/res/values/strings.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/strings.xml.ftl)0
-rw-r--r--templates/activities/BlankActivity/root/src/app_package/DropdownActivity.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/DropdownActivity.java.ftl)0
-rw-r--r--templates/activities/BlankActivity/root/src/app_package/SimpleActivity.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/SimpleActivity.java.ftl)0
-rw-r--r--templates/activities/BlankActivity/root/src/app_package/TabsActivity.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsActivity.java.ftl)0
-rw-r--r--templates/activities/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl)0
-rw-r--r--templates/activities/BlankActivity/template.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml)2
-rw-r--r--templates/activities/BlankActivity/template_blank_activity.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity.png)bin4322 -> 4322 bytes
-rw-r--r--templates/activities/BlankActivity/template_blank_activity_dropdown.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_dropdown.png)bin5662 -> 5662 bytes
-rw-r--r--templates/activities/BlankActivity/template_blank_activity_pager.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_pager.png)bin5441 -> 5441 bytes
-rw-r--r--templates/activities/BlankActivity/template_blank_activity_tabs.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs.png)bin4873 -> 4873 bytes
-rw-r--r--templates/activities/BlankActivity/template_blank_activity_tabs_pager.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs_pager.png)bin5257 -> 5257 bytes
-rw-r--r--templates/activities/MasterDetailFlow/globals.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/globals.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/recipe.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/recipe.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/AndroidManifest.xml.ftl)0
-rwxr-xr-xtemplates/activities/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-large/refs.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values/strings.xml.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl)0
-rw-r--r--templates/activities/MasterDetailFlow/template.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml)0
-rw-r--r--templates/activities/MasterDetailFlow/template_master_detail.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template_master_detail.png)bin7173 -> 7173 bytes
-rw-r--r--templates/other/CustomView/globals.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/globals.xml.ftl)0
-rw-r--r--templates/other/CustomView/recipe.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/recipe.xml.ftl)0
-rwxr-xr-xtemplates/other/CustomView/root/res/layout/sample.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/layout/sample.xml.ftl)0
-rwxr-xr-xtemplates/other/CustomView/root/res/values/attrs.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/values/attrs.xml.ftl)0
-rw-r--r--templates/other/CustomView/root/src/app_package/CustomView.java.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/src/app_package/CustomView.java.ftl)0
-rw-r--r--templates/other/CustomView/template.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/template.xml)0
-rw-r--r--templates/projects/NewAndroidApplication/globals.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/globals.xml.ftl)0
-rw-r--r--templates/projects/NewAndroidApplication/recipe.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/recipe.xml.ftl)0
-rw-r--r--templates/projects/NewAndroidApplication/root/AndroidManifest.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/AndroidManifest.xml.ftl)0
-rw-r--r--templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png)bin3120 -> 3120 bytes
-rwxr-xr-xtemplates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png)bin4996 -> 4996 bytes
-rw-r--r--templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png)bin3030 -> 3030 bytes
-rwxr-xr-xtemplates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png)bin3065 -> 3065 bytes
-rw-r--r--templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png)bin3199 -> 3199 bytes
-rwxr-xr-xtemplates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png)bin6679 -> 6679 bytes
-rw-r--r--templates/projects/NewAndroidApplication/root/res/values-large/dimens.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values-large/dimens.xml)0
-rw-r--r--templates/projects/NewAndroidApplication/root/res/values/dimens.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/dimens.xml)0
-rw-r--r--templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/strings.xml.ftl)0
-rw-r--r--templates/projects/NewAndroidApplication/root/res/values/styles.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/styles.xml)0
-rw-r--r--templates/projects/NewAndroidApplication/template.xml (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml)0
-rw-r--r--templates/projects/NewAndroidApplication/template_new_project.png (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template_new_project.png)bin12408 -> 12408 bytes
-rw-r--r--templates/resources/android-support-v4.jar.bin (renamed from eclipse/plugins/com.android.ide.eclipse.adt/templates/res/android-support-v4.jar.bin)bin247894 -> 247894 bytes
142 files changed, 4361 insertions, 396 deletions
diff --git a/build/product_sdk.mk b/build/product_sdk.mk
index 5646668..f8c39fd 100644
--- a/build/product_sdk.mk
+++ b/build/product_sdk.mk
@@ -40,6 +40,8 @@ PRODUCT_PACKAGES += \
ddms \
ddmuilib \
draw9patch \
+ dvlib \
+ dvlib-tests \
emulator \
hierarchyviewer \
ide_common \
diff --git a/build/sdk_only_whitelist.mk b/build/sdk_only_whitelist.mk
index 3589547..f0acafe 100644
--- a/build/sdk_only_whitelist.mk
+++ b/build/sdk_only_whitelist.mk
@@ -49,6 +49,7 @@ subdirs += \
sdk/assetstudio \
sdk/common \
sdk/ddms \
+ sdk/device_validator \
sdk/eclipse/scripts/rcp \
sdk/hierarchyviewer2 \
sdk/ide_common \
diff --git a/build/tools.atree b/build/tools.atree
index 16fdaf5..414f143 100644
--- a/build/tools.atree
+++ b/build/tools.atree
@@ -108,6 +108,7 @@ framework/lint.jar tools/lib/lint.jar
framework/lint_api.jar tools/lib/lint_api.jar
framework/lint_checks.jar tools/lib/lint_checks.jar
framework/manifmerger.jar tools/lib/manifmerger.jar
+framework/dvlib.jar tools/lib/dvlib.jar
# 3rd Party java libraries
@@ -146,6 +147,13 @@ prebuilts/tools/common/proguard/proguard4.7/bin/proguardgui.sh tools/proguard/bi
prebuilts/tools/common/proguard/proguard4.7/bin/retrace.sh tools/proguard/bin/retrace.sh
prebuilts/tools/common/proguard/proguard4.7/src/proguard/ant/task.properties tools/proguard/ant/task.properties
+# Templates
+sdk/templates/projects/NewAndroidApplication tools/templates/projects/NewAndroidApplication
+sdk/templates/activities/BlankActivity tools/templates/activities/BlankActivity
+sdk/templates/activities/MasterDetailFlow tools/templates/activities/MasterDetailFlow
+sdk/templates/other/CustomView tools/templates/other/CustomView
+sdk/templates/resources tools/templates/resources
+
# SDK Controller
sdk/apps/SdkController tools/apps/SdkController
@@ -163,6 +171,7 @@ framework/common-tests.jar tests/libtests/common-tests.jar
framework/sdklib-tests.jar tests/libtests/sdklib-tests.jar
framework/sdkuilib-tests.jar tests/libtests/sdkuilib-tests.jar
framework/layoutlib_api.jar tests/libtests/layoutlib_api.jar
+framework/dvlib-tests.jar tests/libtests/dvlib-tests.jar
#FIXME breaks build, manifmerger jar files not properly built
#framework/manifmerger-tests.jar tests/libtests/manifmerger-tests.jar
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/AbstractBufferFindTarget.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/AbstractBufferFindTarget.java
new file mode 100644
index 0000000..13a787a
--- /dev/null
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/AbstractBufferFindTarget.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ddmuilib;
+
+import java.util.regex.Pattern;
+
+/**
+ * {@link AbstractBufferFindTarget} implements methods to find items inside a buffer. It takes
+ * care of the logic to search backwards/forwards in the buffer, wrapping around when necessary.
+ * The actual contents of the buffer should be provided by the classes that extend this.
+ */
+public abstract class AbstractBufferFindTarget implements IFindTarget {
+ private int mCurrentSearchIndex;
+
+ // Single element cache of the last search regex
+ private Pattern mLastSearchPattern;
+ private String mLastSearchText;
+
+ @Override
+ public boolean findAndSelect(String text, boolean isNewSearch, boolean searchForward) {
+ boolean found = false;
+ int maxIndex = getItemCount();
+
+ synchronized (this) {
+ // Find starting index for this search
+ if (isNewSearch) {
+ // for new searches, start from an appropriate place as provided by the delegate
+ mCurrentSearchIndex = getStartingIndex();
+ } else {
+ // for ongoing searches (finding next match for the same term), continue from
+ // the current result index
+ mCurrentSearchIndex = getNext(mCurrentSearchIndex, searchForward, maxIndex);
+ }
+
+ // Create a regex pattern based on the search term.
+ Pattern pattern;
+ if (text.equals(mLastSearchText)) {
+ pattern = mLastSearchPattern;
+ } else {
+ pattern = Pattern.compile(text, Pattern.CASE_INSENSITIVE);
+ mLastSearchPattern = pattern;
+ mLastSearchText = text;
+ }
+
+ // Iterate through the list of items. The search ends if we have gone through
+ // all items once.
+ int index = mCurrentSearchIndex;
+ do {
+ String msgText = getItem(mCurrentSearchIndex);
+ if (msgText != null && pattern.matcher(msgText).find()) {
+ found = true;
+ break;
+ }
+
+ mCurrentSearchIndex = getNext(mCurrentSearchIndex, searchForward, maxIndex);
+ } while (index != mCurrentSearchIndex); // loop through entire contents once
+ }
+
+ if (found) {
+ selectAndReveal(mCurrentSearchIndex);
+ }
+
+ return found;
+ }
+
+ /** Indicate that the log buffer has scrolled by certain number of elements */
+ public void scrollBy(int delta) {
+ synchronized (this) {
+ if (mCurrentSearchIndex > 0) {
+ mCurrentSearchIndex = Math.max(0, mCurrentSearchIndex - delta);
+ }
+ }
+ }
+
+ private int getNext(int index, boolean searchForward, int max) {
+ // increment or decrement index
+ index = searchForward ? index + 1 : index - 1;
+
+ // take care of underflow
+ if (index == -1) {
+ index = max - 1;
+ }
+
+ // ..and overflow
+ if (index == max) {
+ index = 0;
+ }
+
+ return index;
+ }
+
+ /** Obtain the number of items in the buffer */
+ public abstract int getItemCount();
+
+ /** Obtain the item at given index */
+ public abstract String getItem(int index);
+
+ /** Select and reveal the item at given index */
+ public abstract void selectAndReveal(int index);
+
+ /** Obtain the index from which search should begin */
+ public abstract int getStartingIndex();
+}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/FindDialog.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/FindDialog.java
new file mode 100644
index 0000000..6370be4
--- /dev/null
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/FindDialog.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ddmuilib;
+
+
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * {@link FindDialog} provides a text box where users can enter text that should be
+ * searched for in the target editor/view. The buttons "Find Previous" and "Find Next"
+ * allow users to search forwards/backwards. This dialog simply provides a front end for the user
+ * and the actual task of searching is delegated to the {@link IFindTarget}.
+ */
+public class FindDialog extends Dialog {
+ private Label mStatusLabel;
+ private Button mFindNext;
+ private Button mFindPrevious;
+ private final IFindTarget mTarget;
+ private Text mSearchText;
+ private String mPreviousSearchText;
+
+ private final static int FIND_NEXT_ID = IDialogConstants.CLIENT_ID;
+ private final static int FIND_PREVIOUS_ID = IDialogConstants.CLIENT_ID + 1;
+
+ public FindDialog(Shell shell, IFindTarget target) {
+ super(shell);
+
+ mTarget = target;
+
+ setShellStyle((getShellStyle() & ~SWT.APPLICATION_MODAL) | SWT.MODELESS);
+ setBlockOnOpen(true);
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite panel = new Composite(parent, SWT.NONE);
+ panel.setLayout(new GridLayout(2, false));
+ panel.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label lblMessage = new Label(panel, SWT.NONE);
+ lblMessage.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+ lblMessage.setText("Find:");
+
+ mSearchText = new Text(panel, SWT.BORDER);
+ mSearchText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+ mSearchText.addModifyListener(new ModifyListener() {
+ @Override
+ public void modifyText(ModifyEvent e) {
+ boolean hasText = !mSearchText.getText().trim().isEmpty();
+ mFindNext.setEnabled(hasText);
+ mFindPrevious.setEnabled(hasText);
+ }
+ });
+
+ mStatusLabel = new Label(panel, SWT.NONE);
+ mStatusLabel.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_DARK_RED));
+ GridData gd = new GridData();
+ gd.horizontalSpan = 2;
+ gd.grabExcessHorizontalSpace = true;
+ mStatusLabel.setLayoutData(gd);
+
+ return panel;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, false);
+ mFindNext = createButton(parent, FIND_NEXT_ID, "Find Next", false);
+ mFindPrevious = createButton(parent, FIND_PREVIOUS_ID, "Find Previous", /* default */ true);
+ mFindNext.setEnabled(false);
+ mFindPrevious.setEnabled(false);
+ }
+
+ @Override
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.CLOSE_ID) {
+ close();
+ return;
+ }
+
+ if (buttonId == FIND_PREVIOUS_ID || buttonId == FIND_NEXT_ID) {
+ if (mTarget != null) {
+ String searchText = mSearchText.getText();
+ boolean newSearch = !searchText.equals(mPreviousSearchText);
+ mPreviousSearchText = searchText;
+ boolean searchForward = buttonId == FIND_NEXT_ID;
+
+ boolean hasMatches = mTarget.findAndSelect(searchText, newSearch, searchForward);
+ if (!hasMatches) {
+ mStatusLabel.setText("String not found");
+ mStatusLabel.pack();
+ } else {
+ mStatusLabel.setText("");
+ }
+ }
+ }
+ }
+}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/IFindTarget.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/IFindTarget.java
new file mode 100644
index 0000000..9aa6943
--- /dev/null
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/IFindTarget.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ddmuilib;
+
+public interface IFindTarget {
+ boolean findAndSelect(String text, boolean isNewSearch, boolean searchForward);
+}
diff --git a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java
index e2fb22f..e7dcec9 100644
--- a/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java
+++ b/ddms/libs/ddmuilib/src/com/android/ddmuilib/logcat/LogCatPanel.java
@@ -21,9 +21,11 @@ import com.android.ddmlib.IDevice;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmuilib.ITableFocusListener;
import com.android.ddmuilib.ITableFocusListener.IFocusedTableActivator;
+import com.android.ddmuilib.FindDialog;
import com.android.ddmuilib.ImageLoader;
import com.android.ddmuilib.SelectionDependentPanel;
import com.android.ddmuilib.TableHelper;
+import com.android.ddmuilib.AbstractBufferFindTarget;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
@@ -908,7 +910,7 @@ public final class LogCatPanel extends SelectionDependentPanel
/** Setup menu to be displayed when right clicking a log message. */
private void addRightClickMenu(final Table table) {
// This action will pop up a create filter dialog pre-populated with current selection
- final Action filterAction = new Action("Filter similar messages..") {
+ final Action filterAction = new Action("Filter similar messages...") {
@Override
public void run() {
List<LogCatMessage> selectedMessages = getSelectedLogCatMessages();
@@ -922,8 +924,16 @@ public final class LogCatPanel extends SelectionDependentPanel
}
};
+ final Action findAction = new Action("Find...") {
+ @Override
+ public void run() {
+ showFindDialog();
+ };
+ };
+
final MenuManager mgr = new MenuManager();
mgr.add(filterAction);
+ mgr.add(findAction);
final Menu menu = mgr.createContextMenu(table);
table.addListener(SWT.MenuDetect, new Listener() {
@@ -1172,6 +1182,8 @@ public final class LogCatPanel extends SelectionDependentPanel
deletedMessageCount = mDeletedLogCount;
mDeletedLogCount = 0;
+
+ mFindTarget.scrollBy(deletedMessageCount);
}
int originalItemCount = mTable.getItemCount();
@@ -1432,4 +1444,53 @@ public final class LogCatPanel extends SelectionDependentPanel
mErrorColor.dispose();
mAssertColor.dispose();
}
+
+ private class LogcatFindTarget extends AbstractBufferFindTarget {
+ @Override
+ public void selectAndReveal(int index) {
+ mTable.deselectAll();
+ mTable.select(index);
+ mTable.showSelection();
+ }
+
+ @Override
+ public int getItemCount() {
+ return mTable.getItemCount();
+ }
+
+ @Override
+ public String getItem(int index) {
+ Object data = mTable.getItem(index).getData();
+ if (data != null) {
+ return data.toString();
+ }
+
+ return null;
+ }
+
+ @Override
+ public int getStartingIndex() {
+ // start searches from current selection if present, otherwise from the tail end
+ // of the buffer
+ int s = mTable.getSelectionIndex();
+ if (s != -1) {
+ return s;
+ } else {
+ return getItemCount() - 1;
+ }
+ };
+ };
+
+ private FindDialog mFindDialog;
+ private LogcatFindTarget mFindTarget = new LogcatFindTarget();
+ public void showFindDialog() {
+ if (mFindDialog != null) {
+ // if the dialog is already displayed
+ return;
+ }
+
+ mFindDialog = new FindDialog(Display.getDefault().getActiveShell(), mFindTarget);
+ mFindDialog.open(); // blocks until find dialog is closed
+ mFindDialog = null;
+ }
}
diff --git a/ddms/libs/ddmuilib/tests/src/com/android/ddmuilib/logcat/RollingBufferFindTest.java b/ddms/libs/ddmuilib/tests/src/com/android/ddmuilib/logcat/RollingBufferFindTest.java
new file mode 100644
index 0000000..32a36c4
--- /dev/null
+++ b/ddms/libs/ddmuilib/tests/src/com/android/ddmuilib/logcat/RollingBufferFindTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ddmuilib.logcat;
+
+import com.android.ddmuilib.AbstractBufferFindTarget;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class RollingBufferFindTest extends TestCase {
+ public class FindTarget extends AbstractBufferFindTarget {
+ private int mSelectedItem = -1;
+ private int mItemReadCount = 0;
+ private List<String> mItems = Arrays.asList(
+ "abc",
+ "def",
+ "abc",
+ null,
+ "xyz"
+ );
+
+ @Override
+ public int getItemCount() {
+ return mItems.size();
+ }
+
+ @Override
+ public String getItem(int index) {
+ mItemReadCount++;
+ return mItems.get(index);
+ }
+
+ @Override
+ public void selectAndReveal(int index) {
+ mSelectedItem = index;
+ }
+
+ @Override
+ public int getStartingIndex() {
+ return mItems.size() - 1;
+ }
+ }
+ FindTarget mFindTarget = new FindTarget();
+
+ public void testMultipleMatch() {
+ mFindTarget.mSelectedItem = -1;
+
+ String text = "abc";
+ int lastIndex = mFindTarget.mItems.lastIndexOf(text);
+ int firstIndex = mFindTarget.mItems.indexOf(text);
+
+ // the first time we search through the buffer we should hit the item at lastIndex
+ assertTrue(mFindTarget.findAndSelect(text, true, false));
+ assertEquals(lastIndex, mFindTarget.mSelectedItem);
+
+ // subsequent search should hit the item at first index
+ assertTrue(mFindTarget.findAndSelect(text, false, false));
+ assertEquals(firstIndex, mFindTarget.mSelectedItem);
+
+ // search again should roll over and hit the last index
+ assertTrue(mFindTarget.findAndSelect(text, false, false));
+ assertEquals(lastIndex, mFindTarget.mSelectedItem);
+ }
+
+ public void testMissingItem() {
+ mFindTarget.mSelectedItem = -1;
+ mFindTarget.mItemReadCount = 0;
+
+ // should not match
+ assertFalse(mFindTarget.findAndSelect("nonexistent", true, false));
+
+ // no item should be selected
+ assertEquals(-1, mFindTarget.mSelectedItem);
+
+ // but all items should have been read in once
+ assertEquals(mFindTarget.getItemCount(), mFindTarget.mItemReadCount);
+ }
+
+ public void testSearchDirection() {
+ String text = "abc";
+ int lastIndex = mFindTarget.mItems.lastIndexOf(text);
+ int firstIndex = mFindTarget.mItems.indexOf(text);
+
+ // the first time we search through the buffer we should hit the "abc" from the last
+ assertTrue(mFindTarget.findAndSelect(text, true, false));
+ assertEquals(lastIndex, mFindTarget.mSelectedItem);
+
+ // searching forward from there should also hit the first index
+ assertTrue(mFindTarget.findAndSelect(text, false, true));
+ assertEquals(firstIndex, mFindTarget.mSelectedItem);
+ }
+}
diff --git a/device_validator/Android.mk b/device_validator/Android.mk
new file mode 100644
index 0000000..9e32461
--- /dev/null
+++ b/device_validator/Android.mk
@@ -0,0 +1,5 @@
+# Copyright 2012 The Android Open Source Project
+
+DEVICE_VALIDATOR_LOCAL_DIR := $(call my-dir)
+include $(DEVICE_VALIDATOR_LOCAL_DIR)/dvlib/Android.mk
+include $(DEVICE_VALIDATOR_LOCAL_DIR)/app/Android.mk
diff --git a/device_validator/MODULE_LICENSE_APACHE2 b/device_validator/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/device_validator/MODULE_LICENSE_APACHE2
diff --git a/device_validator/app/.classpath b/device_validator/app/.classpath
new file mode 100644
index 0000000..a1d7856
--- /dev/null
+++ b/device_validator/app/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/dvlib"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/device_validator/app/.project b/device_validator/app/.project
new file mode 100644
index 0000000..fda9e3d
--- /dev/null
+++ b/device_validator/app/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>device_validator</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/device_validator/app/.settings/org.eclipse.jdt.ui.prefs b/device_validator/app/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..c0fbc32
--- /dev/null
+++ b/device_validator/app/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,3 @@
+#Fri May 25 10:41:24 PDT 2012
+eclipse.preferences.version=1
+formatter_settings_version=11
diff --git a/device_validator/app/Android.mk b/device_validator/app/Android.mk
new file mode 100644
index 0000000..93e6226
--- /dev/null
+++ b/device_validator/app/Android.mk
@@ -0,0 +1,31 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_JAR_MANIFEST := etc/manifest.txt
+
+LOCAL_JAVA_LIBRARIES := \
+ dvlib
+
+LOCAL_MODULE := device_validator
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/device_validator/app/etc/Android.mk b/device_validator/app/etc/Android.mk
new file mode 100644
index 0000000..69a948c
--- /dev/null
+++ b/device_validator/app/etc/Android.mk
@@ -0,0 +1,10 @@
+# Copyright 2012 The Android Open Source Project
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PREBUILT_EXECUTABLES := device_validator
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_PREBUILT)
+
diff --git a/device_validator/app/etc/README b/device_validator/app/etc/README
new file mode 100644
index 0000000..7cf0a0b
--- /dev/null
+++ b/device_validator/app/etc/README
@@ -0,0 +1,19 @@
+Device Validator
+================
+ The device validator is a simple tool for validating XML that contains
+ information about a list of Android devices. Simply run the tool from the
+ command-line with the names of the XML files to validate as the arguments.
+ If an XML file fails to validate, the errors will be printed to standard
+ out and the program will terminate with a non-zero exit status.
+
+ See device_example.xml for an example valid XML file, and devices.xsd
+ for the schema the XML must conform to.
+
+Usage (Linux/OSX/BSD)
+---------------------
+ ./device_validator [files...]
+
+Usage (Windows)
+---------------
+ (from the untar'd directory)
+ java -cp . -jar device_validator.jar [files...]
diff --git a/device_validator/app/etc/device_validator b/device_validator/app/etc/device_validator
new file mode 100755
index 0000000..08a1023
--- /dev/null
+++ b/device_validator/app/etc/device_validator
@@ -0,0 +1,79 @@
+#!/bin/bash
+# Copyright 2012, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Set up prog to be the path of this script, including following symlinks,
+# and set up progdir to be the fully-qualified pathname of its directory.
+prog="$0"
+while [ -h "${prog}" ]; do
+ newProg=`/bin/ls -ld "${prog}"`
+ newProg=`expr "${newProg}" : ".* -> \(.*\)$"`
+ if expr "x${newProg}" : 'x/' >/dev/null; then
+ prog="${newProg}"
+ else
+ progdir=`dirname "${prog}"`
+ prog="${progdir}/${newProg}"
+ fi
+done
+oldwd=`pwd`
+progdir=`dirname "${prog}"`
+cd "${progdir}"
+progdir=`pwd`
+prog="${progdir}"/`basename "${prog}"`
+cd "${oldwd}"
+
+jarfile=device_validator.jar
+frameworkdir="$progdir"
+libdir="$progdir"
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+ frameworkdir=`dirname "$progdir"`/tools/lib
+ libdir=`dirname "$progdir"`/tools/lib
+fi
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+ frameworkdir=`dirname "$progdir"`/framework
+ libdir=`dirname "$progdir"`/lib
+fi
+if [ ! -r "$frameworkdir/$jarfile" ]
+then
+ echo `basename "$prog"`": can't find $jarfile"
+ exit 1
+fi
+
+
+# Check args.
+if [ debug = "$1" ]; then
+ # add this in for debugging
+ java_debug=-agentlib:jdwp=transport=dt_socket,server=y,address=8050,suspend=y
+ shift 1
+else
+ java_debug=
+fi
+
+javaCmd="java"
+
+# Mac OS X needs an additional arg, or you get an "illegal thread" complaint.
+if [ `uname` = "Darwin" ]; then
+ os_opts="-XstartOnFirstThread"
+else
+ os_opts=
+fi
+
+jarpath="$frameworkdir/$jarfile"
+
+exec "$javaCmd" \
+ -Xmx256M $os_opts $java_debug \
+ -classpath "$jarpath" \
+ com.android.validator.DeviceValidator "$@"
diff --git a/device_validator/app/etc/manifest.txt b/device_validator/app/etc/manifest.txt
new file mode 100644
index 0000000..55b9038
--- /dev/null
+++ b/device_validator/app/etc/manifest.txt
@@ -0,0 +1,3 @@
+Main-Class: com.android.validator.DeviceValidator
+Class-Path: dvlib.jar
+
diff --git a/device_validator/app/src/com/android/validator/DeviceValidator.java b/device_validator/app/src/com/android/validator/DeviceValidator.java
new file mode 100644
index 0000000..e4038bc
--- /dev/null
+++ b/device_validator/app/src/com/android/validator/DeviceValidator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 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.validator;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+import com.android.dvlib.DeviceSchema;
+
+public class DeviceValidator {
+
+ public static void main(String[] args) {
+ if (args.length == 0){
+ printHelp();
+ System.exit(1);
+ }
+ int ret = 0;
+ for (String a : args) {
+ File f = (new File(a)).getAbsoluteFile();
+ try {
+ if (!DeviceSchema.validate(new FileInputStream(f), System.err, f.getParentFile())) {
+ System.err.println("Error validating " + f.getAbsolutePath());
+ System.out.println();
+ ret = 1;
+ } else {
+ System.out.println(f.getAbsolutePath() + " validated successfully.");
+ }
+ } catch (FileNotFoundException e) {
+ System.err.println("File not found: " + a);
+ ret = 1;
+ }
+ }
+ System.exit(ret);
+ }
+
+ private static void printHelp() {
+ System.err.printf("Usage: device_validator [files to validate]...\n");
+ }
+
+}
diff --git a/device_validator/dvlib/.classpath b/device_validator/dvlib/.classpath
new file mode 100644
index 0000000..88fb9b4
--- /dev/null
+++ b/device_validator/dvlib/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="tests/src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/device_validator/dvlib/.gitignore b/device_validator/dvlib/.gitignore
new file mode 100644
index 0000000..e660fd9
--- /dev/null
+++ b/device_validator/dvlib/.gitignore
@@ -0,0 +1 @@
+bin/
diff --git a/device_validator/dvlib/.project b/device_validator/dvlib/.project
new file mode 100644
index 0000000..13abbdf
--- /dev/null
+++ b/device_validator/dvlib/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>dvlib</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/device_validator/dvlib/Android.mk b/device_validator/dvlib/Android.mk
new file mode 100644
index 0000000..1869adb
--- /dev/null
+++ b/device_validator/dvlib/Android.mk
@@ -0,0 +1,26 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_RESOURCE_DIRS := src
+
+LOCAL_MODULE := dvlib
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java b/device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java
new file mode 100644
index 0000000..101baf4
--- /dev/null
+++ b/device_validator/dvlib/src/com/android/dvlib/DeviceSchema.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2012 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.dvlib;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class DeviceSchema {
+
+ public static final String NS_DEVICES_XSD = "http://schemas.android.com/sdk/devices/1";
+
+ /**
+ * The "devices" element is the root element of this schema.
+ *
+ * It must contain one or more "device" elements that each define the
+ * hardware, software, and states for a given device.
+ */
+ public static final String NODE_DEVICES = "devices";
+
+ /**
+ * A "device" element contains a "hardware" element, a "software" element
+ * for each API version it supports, and a "state" element for each possible
+ * state the device could be in.
+ */
+ public static final String NODE_DEVICE = "device";
+
+ /**
+ * The "hardware" element contains all of the hardware information for a
+ * given device.
+ */
+ public static final String NODE_HARDWARE = "hardware";
+
+ /**
+ * The "software" element contains all of the software information for an
+ * API version of the given device.
+ */
+ public static final String NODE_SOFTWARE = "software";
+
+ /**
+ * The "state" element contains all of the parameters for a given state of
+ * the device. It's also capable of redefining hardware configurations if
+ * they change based on state.
+ */
+ public static final String NODE_STATE = "state";
+
+ public static final String NODE_KEYBOARD = "keyboard";
+
+ public static final String NODE_TOUCH = "touch";
+
+ public static final String NODE_GL_EXTENSIONS = "gl-extensions";
+
+ public static final String NODE_GL_VERSION = "gl-version";
+
+ public static final String NODE_NETWORKING = "networking";
+
+ public static final String NODE_REMOVABLE_STORAGE = "removable-storage";
+
+ public static final String NODE_FLASH = "flash";
+
+ public static final String NODE_LIVE_WALLPAPER_SUPPORT = "live-wallpaper-support";
+
+ public static final String NODE_BUTTONS = "buttons";
+
+ public static final String NODE_CAMERA = "camera";
+
+ public static final String NODE_LOCATION = "location";
+
+ public static final String NODE_GPU = "gpu";
+
+ public static final String NODE_DOCK = "dock";
+
+ public static final String NODE_YDPI = "ydpi";
+
+ public static final String NODE_PLUGGED_IN = "plugged-in";
+
+ public static final String NODE_Y_DIMENSION = "y-dimension";
+
+ public static final String NODE_SCREEN_RATIO = "screen-ratio";
+
+ public static final String NODE_NAV_STATE = "nav-state";
+
+ public static final String NODE_HAS_MIC = "has-mic";
+
+ public static final String NODE_RAM = "ram";
+
+ public static final String NODE_XDPI = "xdpi";
+
+ public static final String NODE_DIMENSIONS = "dimensions";
+
+ public static final String NODE_ABI = "abi";
+
+ public static final String NODE_MECHANISM = "mechanism";
+
+ public static final String NODE_MULTITOUCH = "multitouch";
+
+ public static final String NODE_NAV = "nav";
+
+ public static final String NODE_PIXEL_DENSITY = "pixel-density";
+
+ public static final String NODE_SCREEN_ORIENTATION = "screen-orientation";
+
+ public static final String NODE_AUTOFOCUS = "autofocus";
+
+ public static final String NODE_SCREEN_SIZE = "screen-size";
+
+ public static final String NODE_DESCRIPTION = "description";
+
+ public static final String NODE_BLUETOOTH_PROFILES = "bluetooth-profiles";
+
+ public static final String NODE_SCREEN = "screen";
+
+ public static final String NODE_SENSORS = "sensors";
+
+ public static final String NODE_DIAGONAL_LENGTH = "diagonal-length";
+
+ public static final String NODE_SCREEN_TYPE = "screen-type";
+
+ public static final String NODE_KEYBOARD_STATE = "keyboard-state";
+
+ public static final String NODE_X_DIMENSION = "x-dimension";
+
+ public static final String NODE_CPU = "cpu";
+
+ public static final String NODE_INTERNAL_STORAGE = "internal-storage";
+
+ public static final String NODE_META = "meta";
+
+ public static final String NODE_ICONS = "icons";
+
+ public static final String NODE_SIXTY_FOUR = "sixty-four";
+
+ public static final String NODE_SIXTEEN = "sixteen";
+
+ public static final String NODE_FRAME = "frame";
+
+ public static final String NODE_PATH = "path";
+
+ public static final String NODE_PORTRAIT_X_OFFSET = "portrait-x-offset";
+
+ public static final String NODE_PORTRAIT_Y_OFFSET = "portrait-y-offset";
+
+ public static final String NODE_LANDSCAPE_X_OFFSET = "landscape-x-offset";
+
+ public static final String NODE_LANDSCAPE_Y_OFFSET = "landscape-y-offset";
+
+ public static final String NODE_NAME = "name";
+
+ public static final String NODE_API_LEVEL = "api-level";
+
+ public static final String NODE_MANUFACTURER = "manufacturer";
+
+ public static final String ATTR_DEFAULT = "default";
+
+ public static final String ATTR_UNIT = "unit";
+
+ /**
+ * Validates the input stream.
+ *
+ * @param deviceXml
+ * The XML InputStream to validate.
+ * @param out
+ * The OutputStream for error messages.
+ * @param parent
+ * The parent directory of the input stream.
+ * @return Whether the given input constitutes a valid devices file.
+ */
+ public static boolean validate(InputStream deviceXml, OutputStream out, File parent) {
+ Schema s;
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ PrintWriter writer = new PrintWriter(out);
+ try {
+ s = DeviceSchema.getSchema();
+ factory.setValidating(false);
+ factory.setNamespaceAware(true);
+ factory.setSchema(s);
+ ValidationHandler validator = new ValidationHandler(parent, writer);
+ SAXParser parser = factory.newSAXParser();
+ parser.parse(deviceXml, validator);
+ return validator.isValidDevicesFile();
+ } catch (SAXException e) {
+ writer.println(e.getMessage());
+ return false;
+ } catch (ParserConfigurationException e) {
+ writer.println("Error creating SAX parser:");
+ writer.println(e.getMessage());
+ return false;
+ } catch (IOException e) {
+ writer.println("Error reading file stream:");
+ writer.println(e.getMessage());
+ return false;
+ } finally {
+ writer.flush();
+ }
+ }
+
+ /**
+ * Helper to get an input stream of the device config XML schema.
+ */
+ public static InputStream getXsdStream() {
+ return DeviceSchema.class.getResourceAsStream("devices.xsd"); //$NON-NLS-1$
+ }
+
+ /** Helper method that returns a {@link Validator} for our XSD */
+ public static Schema getSchema() throws SAXException {
+ InputStream xsdStream = getXsdStream();
+ SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ Schema schema = factory.newSchema(new StreamSource(xsdStream));
+ return schema;
+ }
+
+ /**
+ * A DefaultHandler that parses only to validate the XML is actually a valid
+ * devices config, since validation can't be entirely encoded in the devices
+ * schema.
+ */
+ private static class ValidationHandler extends DefaultHandler {
+ private boolean mValidDevicesFile = true;
+ private boolean mDefaultSeen = false;
+ private String mDeviceName;
+ private final File mDirectory;
+ private final PrintWriter mWriter;
+ private final StringBuilder mStringAccumulator = new StringBuilder();
+
+ public ValidationHandler(File directory, PrintWriter writer) {
+ mDirectory = directory; // Possibly null
+ mWriter = writer;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String name, Attributes attributes)
+ throws SAXException {
+ if (NODE_DEVICE.equals(localName)) {
+ // Reset for a new device
+ mDefaultSeen = false;
+ } else if (NODE_STATE.equals(localName)) {
+ // Check if the state is set to be a default state
+ String val = attributes.getValue(ATTR_DEFAULT);
+ if (val != null && ("1".equals(val) || Boolean.parseBoolean(val))) {
+ /*
+ * If it is and we already have a default state for this
+ * device, then the device configuration is invalid.
+ * Otherwise, set that we've seen a default state for this
+ * device and continue
+ */
+
+ if (mDefaultSeen) {
+ validationError("More than one default state for device " + mDeviceName);
+ } else {
+ mDefaultSeen = true;
+ }
+ }
+ }
+ mStringAccumulator.setLength(0);
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ mStringAccumulator.append(ch, start, length);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String name) throws SAXException {
+ // If this is the end of a device node, make sure we have at least
+ // one default state
+ if (NODE_DEVICE.equals(localName) && !mDefaultSeen) {
+ validationError("No default state for device " + mDeviceName);
+ } else if (NODE_NAME.equals(localName)) {
+ mDeviceName = mStringAccumulator.toString().trim();
+ } else if (NODE_PATH.equals(localName) || NODE_SIXTY_FOUR.equals(localName)
+ || NODE_SIXTEEN.equals(localName)) {
+ if (mDirectory == null) {
+ // There is no given parent directory, so this is not a
+ // valid devices file
+ validationError("No parent directory given, but relative paths exist.");
+ return;
+ }
+ // This is going to break on any files that end with a space,
+ // but that should be an incredibly rare corner case.
+ String relativePath = mStringAccumulator.toString().trim();
+ File f = new File(mDirectory, relativePath);
+ if (f == null || !f.isFile()) {
+ validationError(relativePath + " is not a valid path.");
+ return;
+ }
+ String fileName = f.getName();
+ int extensionStart = fileName.lastIndexOf(".");
+ if (extensionStart == -1 || !fileName.substring(extensionStart + 1).equals("png")) {
+ validationError(relativePath + " is not a valid file type.");
+ }
+ }
+ }
+
+ @Override
+ public void error(SAXParseException e) {
+ validationError(e.getMessage());
+ }
+
+ @Override
+ public void fatalError(SAXParseException e) {
+ validationError(e.getMessage());
+ }
+
+ public boolean isValidDevicesFile() {
+ return mValidDevicesFile;
+ }
+
+ private void validationError(String reason) {
+ mWriter.println("Error: " + reason);
+ mValidDevicesFile = false;
+ }
+
+ }
+}
diff --git a/device_validator/dvlib/src/com/android/dvlib/devices.xsd b/device_validator/dvlib/src/com/android/dvlib/devices.xsd
new file mode 100644
index 0000000..c3fa482
--- /dev/null
+++ b/device_validator/dvlib/src/com/android/dvlib/devices.xsd
@@ -0,0 +1,884 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright (C) 2012 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/devices/1"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:c="http://schemas.android.com/sdk/devices/1"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+ version="1">
+
+ <xsd:element name="devices" type="c:devicesType" />
+
+ <xsd:complexType name="devicesType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The "devices" element is the root element of this schema.
+
+ It must contain one or more "device" elements that each define the configurations
+ and states available for a given device.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="device" minOccurs="1" maxOccurs="unbounded">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ A device element contains one hardware profile for a device, along with
+ 1 or more software profiles and 1 or more states. Each software profile
+ defines the supported software for a given API release, and each state
+ profile defines a different possible state of the device (screen in
+ portrait orientation, screen in landscape orientation with the keyboard
+ out, etc.)
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="name" type= "xsd:token" />
+ <xsd:element name="manufacturer" type= "xsd:token" />
+ <xsd:element name="meta" type= "c:metaType" minOccurs="0" />
+ <xsd:element name="hardware" type= "c:hardwareType" />
+ <xsd:element name="software" type= "c:softwareType"
+ maxOccurs="unbounded" />
+ <xsd:element name="state" type= "c:stateType"
+ maxOccurs="unbounded" />
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="hardwareType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The hardwareType contains all of the hardware information for
+ a given device. This includes things like the GPU type, screen
+ size, mic presence, etc.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="screen" type= "c:screenType" />
+ <xsd:element name="networking" type= "c:networkingType" />
+ <xsd:element name="sensors" type= "c:sensorsType" />
+ <xsd:element name="mic" type= "c:micType" />
+ <xsd:element name="camera" type= "c:cameraType"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="keyboard" type= "c:keyboardType" />
+ <xsd:element name="nav" type= "c:navType" />
+ <xsd:element name="ram" type= "c:ramType" />
+ <xsd:element name="buttons" type= "c:buttonsType" />
+ <xsd:element name="internal-storage" type= "c:internalStorageType" />
+ <xsd:element name="removable-storage" type= "c:removableStorageType" />
+ <xsd:element name="cpu" type= "c:cpuType" />
+ <xsd:element name="gpu" type= "c:gpuType" />
+ <xsd:element name="abi" type= "c:abiType" />
+ <xsd:element name="dock" type= "c:dockType" />
+ <xsd:element name="plugged-in" type= "c:pluggedInType" />
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="softwareType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The softwareType contains all of the device's software
+ information for a given API version. This includes things like
+ live wallpaper support, OpenGL version, etc.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="api-level">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies which API version(s) this this element is
+ defining. This can in the form of a single number
+ or a range of low to high, separated with a dash and
+ with either limit missing. The default lower limit is
+ one, and the default upper limit is unbounded.
+ The following are valid:
+ 10
+ 7-10
+ -10
+ 7-
+ -
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:pattern value="[\d]*-[\d]*|[\d]+" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:element name="live-wallpaper-support" type="xsd:boolean">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies whether the device supports live wallpapers.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <xsd:element name="bluetooth-profiles">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies all of the available Bluetooth profiles.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:NMTOKEN">
+ <xsd:enumeration value="A2DP" />
+ <xsd:enumeration value="ATT" />
+ <xsd:enumeration value="AVRCP" />
+ <xsd:enumeration value="AVDTP" />
+ <xsd:enumeration value="BIP" />
+ <xsd:enumeration value="BPP" />
+ <xsd:enumeration value="CIP" />
+ <xsd:enumeration value="CTP" />
+ <xsd:enumeration value="DIP" />
+ <xsd:enumeration value="DUN" />
+ <xsd:enumeration value="FAX" />
+ <xsd:enumeration value="FTP" />
+ <xsd:enumeration value="GAVDP" />
+ <xsd:enumeration value="GAP" />
+ <xsd:enumeration value="GATT" />
+ <xsd:enumeration value="GOEP" />
+ <xsd:enumeration value="HCRP" />
+ <xsd:enumeration value="HDP" />
+ <xsd:enumeration value="HFP" />
+ <xsd:enumeration value="HID" />
+ <xsd:enumeration value="HSP" />
+ <xsd:enumeration value="ICP" />
+ <xsd:enumeration value="LAP" />
+ <xsd:enumeration value="MAP" />
+ <xsd:enumeration value="OPP" />
+ <xsd:enumeration value="PAN" />
+ <xsd:enumeration value="PBA" />
+ <xsd:enumeration value="PBAP" />
+ <xsd:enumeration value="SPP" />
+ <xsd:enumeration value="SDAP" />
+ <xsd:enumeration value="SAP" />
+ <xsd:enumeration value="SIM" />
+ <xsd:enumeration value="rSAP" />
+ <xsd:enumeration value="SYNCH" />
+ <xsd:enumeration value="VDP" />
+ <xsd:enumeration value="WAPB" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="gl-version">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the OpenGL version supported for this release.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:decimal">
+ <xsd:pattern value="[0-9]\.[0-9]" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="gl-extensions">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies all of the supported OpenGL extensions for
+ this release.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:list itemType="xsd:NMTOKEN" />
+ </xsd:simpleType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="stateType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The stateType contains the information for a given state of
+ of the device. States include things like portrait mode,
+ landscape with the keyboard exposed, etc. States can also
+ modify the hardware attributes of a device. For instance, if
+ sliding out the keyboard increased the available screen
+ real estate, you can define a new screenType to override the
+ default one defined in the device's hardwareType.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="description" type="xsd:token">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ A description of the defined state.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <xsd:element name="screen-orientation">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Defines the orientation of the screen. Use square if
+ the device's screen has equal height and width,
+ otherwise use landscape or portrait.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="portrait" />
+ <xsd:enumeration value="landscape" />
+ <xsd:enumeration value="square" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="keyboard-state">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Defines the state of the keyboard. If the device has no
+ keyboard use keysoft, otherwise use keysexposed or keyshidden.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="keyssoft" />
+ <xsd:enumeration value="keyshidden" />
+ <xsd:enumeration value="keysexposed" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:element name="nav-state">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Defines the state of the primary non-touchscreen
+ navigation hardware on the devices. If the device
+ doesn't have non-touchscreen navigation hardware use
+ nonav, otherwise use navexposed or navhidden.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="nonav" />
+ <xsd:enumeration value="navhidden" />
+ <xsd:enumeration value="navexposed" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:element name="screen" type="c:screenType" minOccurs="0" />
+ <xsd:element name="networking" type="c:networkingType"
+ minOccurs="0" />
+ <xsd:element name="sensors" type="c:sensorsType" minOccurs="0" />
+ <xsd:element name="mic" type="c:micType" minOccurs="0" />
+ <xsd:element name="camera" type="c:cameraType"
+ minOccurs="0" maxOccurs="unbounded" />
+ <xsd:element name="keyboard" type="c:keyboardType" minOccurs="0" />
+ <xsd:element name="nav" type="c:navType" minOccurs="0" />
+ <xsd:element name="ram" type="c:ramType" minOccurs="0" />
+ <xsd:element name="buttons" type="c:buttonsType" minOccurs="0" />
+ <xsd:element name="internal-storage" type="c:internalStorageType"
+ minOccurs="0" />
+ <xsd:element name="removable-storage" type="c:removableStorageType"
+ minOccurs="0" />
+ <xsd:element name="cpu" type="c:cpuType" minOccurs="0" />
+ <xsd:element name="gpu" type="c:gpuType" minOccurs="0" />
+ <xsd:element name="abi" type="c:abiType" minOccurs="0" />
+ <xsd:element name="dock" type="c:dockType" minOccurs="0" />
+ <xsd:element name="plugged-in" type="c:pluggedInType"
+ minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:token" />
+ <xsd:attribute name="default" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+
+ <xsd:complexType name="metaType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Details where more device information can be found, such as
+ icons and frame images.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="icons" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Contains the relative paths to the icon files for this
+ device.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="sixty-four" type="xsd:normalizedString">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Relative path for the 64x64 icon.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="sixteen" type="xsd:normalizedString"
+ minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Relative path for the 16x16 icon.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="frame" minOccurs="0">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Contains information about the frame for the device.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="path"
+ type="xsd:normalizedString">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The relative path to the emulator frame for
+ the device.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="portrait-x-offset"
+ type="xsd:nonNegativeInteger">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The offset for the frame in the x direction,
+ in portrait mode.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="portrait-y-offset"
+ type="xsd:nonNegativeInteger">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The offset for the frame in the y direction,
+ in portrait mode.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="landscape-x-offset"
+ type="xsd:nonNegativeInteger">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The offset for the frame in the x direction,
+ in landscape mode.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ <xsd:element name="landscape-y-offset"
+ type="xsd:nonNegativeInteger">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ The offset for the frame in the y direction,
+ in landscape mode.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:complexType name="screenType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Contains the specifications for the device's screen.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="screen-size">
+ <xsd:simpleType>
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the class of the screen.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="small" />
+ <xsd:enumeration value="normal" />
+ <xsd:enumeration value="large" />
+ <xsd:enumeration value="xlarge" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="diagonal-length">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the diagonal length of the screen in inches.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:decimal">
+ <!-- Negative lengths are not valid -->
+ <xsd:minInclusive value="0" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="pixel-density">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the screen density of the device. The
+ medium density of traditional HVGA screens (mdpi)
+ is defined to be approximately 160dpi; low density
+ (ldpi) is 120, and high density (hdpi) is 240. There
+ is thus a 4:3 scaling factor between each density,
+ so a 9x9 bitmap in ldpi would be 12x12 in mdpi and
+ 16x16 in hdpi.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="ldpi" />
+ <xsd:enumeration value="mdpi" />
+ <xsd:enumeration value="tvdpi" />
+ <xsd:enumeration value="hdpi" />
+ <xsd:enumeration value="xhdpi" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="screen-ratio">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies whether the configuration is for a taller or
+ wider than traditional screen. This is based purely on
+ the aspect ratio of the screen: QVGA, HVGA, and VGA are
+ notlong; WQVGA, WVGA, FWVGA are long. Note that long may
+ mean either wide or tall, depending on the current
+ orientation.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="notlong" />
+ <xsd:enumeration value="long" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="dimensions">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the device screen resolution in pixels.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="x-dimension">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the x-dimension's resolution in
+ pixels.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:positiveInteger" />
+ </xsd:simpleType>
+ </xsd:element>
+ <xsd:element name="y-dimension">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the y-dimension's resolution in
+ pixels.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:positiveInteger" />
+ </xsd:simpleType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="xdpi">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the actual density in X of the device screen.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:decimal">
+ <!-- Negative DPIs are not valid -->
+ <xsd:minInclusive value="0" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="ydpi">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the actual density in Y of the device screen.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:decimal">
+ <!-- Negative DPIs are not valid -->
+ <xsd:minInclusive value="0" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="touch">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the touch properties of the device.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="multitouch">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the multitouch capabilities of the
+ device. This can be none if multitouch is
+ not supported, basic if the device can track
+ only basic two finger gestures, distinct if
+ the device can track two or more fingers
+ simultaneously, or jazz-hands if the device
+ can track 5 or more fingers simultaneously.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="none" />
+ <xsd:enumeration value="basic" />
+ <xsd:enumeration value="distinct" />
+ <xsd:enumeration value="jazz-hands" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="mechanism">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the mechanism the device was
+ created for.
+ </xsd:documentation>
+ </xsd:annotation>
+ <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="screen-type">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the type of touch screen on the
+ device.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="notouch" />
+ <xsd:enumeration value="capacitive" />
+ <xsd:enumeration value="resistive" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:simpleType name="networkingType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the available networking hardware.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="NFC" />
+ <xsd:enumeration value="Bluetooth" />
+ <xsd:enumeration value="Wifi" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="sensorsType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the available sensors.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="Accelerometer" />
+ <xsd:enumeration value="Barometer" />
+ <xsd:enumeration value="Compass" />
+ <xsd:enumeration value="GPS" />
+ <xsd:enumeration value="Gyroscope" />
+ <xsd:enumeration value="LightSensor" />
+ <xsd:enumeration value="ProximitySensor" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="micType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies whether the device has a mic or not.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:boolean" />
+ </xsd:simpleType>
+
+ <xsd:complexType name="cameraType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the attributes of the camera.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:sequence>
+ <xsd:element name="location">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the location of the camera.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="front" />
+ <xsd:enumeration value="back" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:element>
+
+ <xsd:element name="autofocus" type="xsd:boolean">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies whether the camera can autofocus
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+
+ <xsd:element name="flash" type="xsd:boolean">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies whether the camera has flash.
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+
+ <xsd:simpleType name="keyboardType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the type of keyboard on the device.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="qwerty" />
+ <xsd:enumeration value="12key" />
+ <xsd:enumeration value="nokeys" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="navType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the primary non-touchscreen navigation
+ hardware on the device.
+ </xsd:documentation>
+ </xsd:annotation>
+ <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:complexType name="ramType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the amount of RAM on the device in the unit provided.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="xsd:positiveInteger">
+ <xsd:attribute name="unit" type="c:storageUnitType" use="required" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:simpleType name="buttonsType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies whether the device has physical (hard) buttons
+ (Home, Search, etc.), or uses soft buttons.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="hard" />
+ <xsd:enumeration value="soft" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:complexType name="internalStorageType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ A list specifying the sizes of internal storage in
+ the device, in the storage size unit provided.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="c:storageListType">
+ <xsd:attribute name="unit" type="c:storageUnitType"
+ use="required" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:complexType name="removableStorageType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the range of available removable storage sizes
+ in the unit provided. A positive value indicates the device is
+ available with that storage size included while a zero value
+ indicates an empty storage slot.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:simpleContent>
+ <xsd:extension base="c:storageListType">
+ <xsd:attribute name="unit" type="c:storageUnitType"
+ use="required" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+ <xsd:simpleType name="storageListType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Defines a list for storage configurations such as internal or
+ removable storage. A positive value indicates the the device
+ has a storage unit of that size, while a zero value indicates
+ there is an empty location for a storage unit (such as an empty
+ SD card slot).
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:nonNegativeInteger" />
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+ <xsd:simpleType name="gpuType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the device's GPU.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:minLength value="1" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="cpuType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the device's CPU.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:minLength value="1" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="abiType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies which ABIs the device conforms to.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="armeabi" />
+ <xsd:enumeration value="armeabi-v7a" />
+ <xsd:enumeration value="x86" />
+ <xsd:enumeration value="mips" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="dockType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the official docks available for the device.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:list>
+ <xsd:simpleType>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="desk" />
+ <xsd:enumeration value="tv" />
+ <xsd:enumeration value="car" />
+ </xsd:restriction>
+ </xsd:simpleType>
+ </xsd:list>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="pluggedInType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies when the device is plugged in.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="always" />
+ <xsd:enumeration value="charge" />
+ <xsd:enumeration value="never" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:simpleType name="storageUnitType">
+ <xsd:annotation>
+ <xsd:documentation xml:lang="en">
+ Specifies the unit of storage. This can be MiB, GiB, etc.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:restriction base="xsd:token">
+ <xsd:enumeration value="B" />
+ <xsd:enumeration value="KiB" />
+ <xsd:enumeration value="MiB" />
+ <xsd:enumeration value="GiB" />
+ <xsd:enumeration value="TiB" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+</xsd:schema>
diff --git a/device_validator/dvlib/tests/Android.mk b/device_validator/dvlib/tests/Android.mk
new file mode 100644
index 0000000..5094d7a
--- /dev/null
+++ b/device_validator/dvlib/tests/Android.mk
@@ -0,0 +1,30 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_JAVA_RESOURCE_DIRS := src
+
+LOCAL_MODULE := dvlib-tests
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := \
+ dvlib \
+ junit
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/DeviceSchemaTest.java b/device_validator/dvlib/tests/src/com/android/dvlib/DeviceSchemaTest.java
new file mode 100644
index 0000000..174f27c
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/DeviceSchemaTest.java
@@ -0,0 +1,311 @@
+package com.android.dvlib;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import junit.framework.TestCase;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class DeviceSchemaTest extends TestCase {
+
+ private void checkFailure(Map<String, String> replacements, String regex) throws Exception {
+ // Generate XML stream with replacements
+ InputStream xmlStream = getReplacedStream(replacements);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ URL location = DeviceSchemaTest.class.getResource(".");
+ File parent = new File(location.toURI());
+ assertFalse(
+ "Validation Assertion Failed, XML failed to validate when it was expected to pass\n",
+ DeviceSchema.validate(xmlStream, baos, parent));
+ assertTrue(String.format("Regex Assertion Failed:\nExpected: %s\nActual: %s\n", regex, baos
+ .toString().trim()), baos.toString().trim().matches(regex));
+ }
+
+ private void checkFailure(String resource, String regex) throws Exception {
+ URL location = DeviceSchemaTest.class.getResource(resource);
+ File xml = new File(location.toURI());
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ assertFalse("Validation Assertion Failed, XML validated when it was expected to fail\n",
+ DeviceSchema.validate(new FileInputStream(xml), baos, xml.getParentFile()));
+ assertTrue(String.format("Regex Assertion Failed:\nExpected: %s\nActual: %s\n", regex, baos
+ .toString().trim()), baos.toString().trim().matches(regex));
+ }
+
+ private void checkSuccess(Map<String, String> replacements) throws Exception {
+ InputStream xmlStream = getReplacedStream(replacements);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ URL location = DeviceSchemaTest.class.getResource(".");
+ File parent = new File(location.toURI());
+ assertTrue(DeviceSchema.validate(xmlStream, baos, parent));
+ assertTrue(baos.toString().trim().matches(""));
+ }
+
+ private InputStream getReplacedStream(Map<String, String> replacements) throws Exception {
+ URL location = DeviceSchema.class.getResource("devices_minimal.xml");
+ File xml = new File(location.toURI());
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ SAXParser parser = factory.newSAXParser();
+ ReplacementHandler replacer = new ReplacementHandler(replacements);
+ parser.parse(xml, replacer);
+ Document doc = replacer.getGeneratedDocument();
+ Transformer tf = TransformerFactory.newInstance().newTransformer();
+ // Add indents so we're closer to user generated output
+ tf.setOutputProperty(OutputKeys.INDENT, "yes");
+ DOMSource source = new DOMSource(doc);
+ StringWriter out = new StringWriter();
+ StreamResult result = new StreamResult(out);
+ tf.transform(source, result);
+ return new ByteArrayInputStream(out.toString().getBytes("UTF-8"));
+ }
+
+ public void testValidXml() throws Exception {
+ URL location = DeviceSchemaTest.class.getResource("devices.xml");
+ File xml = new File(location.toURI());
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ boolean result = DeviceSchema.validate(new FileInputStream(xml), baos, xml.getParentFile());
+ String output = baos.toString().trim();
+ assertTrue(
+ String.format(
+ "Validation Assertion Failed, XML failed to validate when it was expected to pass\n%s\n",output), result);
+ assertTrue(String.format("Regex Assertion Failed\nExpected No Output\nActual: %s\n", baos
+ .toString().trim()), baos.toString().trim().matches(""));
+ }
+
+ public void testNoHardware() throws Exception {
+ String regex = "Error: cvc-complex-type.2.4.a: Invalid content was found starting with "
+ + "element 'd:software'.*";
+ checkFailure("devices_no_hardware.xml", regex);
+ }
+
+ public void testNoSoftware() throws Exception {
+ String regex = "Error: cvc-complex-type.2.4.a: Invalid content was found starting with "
+ + "element 'd:state'.*";
+ checkFailure("devices_no_software.xml", regex);
+ }
+
+ public void testNoDefault() throws Exception {
+ String regex = "Error: No default state for device Galaxy Nexus.*";
+ checkFailure("devices_no_default.xml", regex);
+ }
+
+ public void testTooManyDefaults() throws Exception {
+ String regex = "Error: More than one default state for device Galaxy Nexus.*";
+ checkFailure("devices_too_many_defaults.xml", regex);
+ }
+
+ public void testNoStates() throws Exception {
+ String regex = "Error: cvc-complex-type.2.4.b: The content of element 'd:device' is not "
+ + "complete.*\nError: No default state for device Galaxy Nexus.*";
+ checkFailure("devices_no_states.xml", regex);
+ }
+
+ public void testBadMechanism() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_MECHANISM, "fanger");
+ checkFailure(replacements, "Error: cvc-enumeration-valid: Value 'fanger' is not "
+ + "facet-valid.*\nError: cvc-type.3.1.3: The value 'fanger' of element "
+ + "'d:mechanism' is not valid.*");
+ }
+
+ public void testNegativeXdpi() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_XDPI, "-1.0");
+ checkFailure(replacements, "Error: cvc-minInclusive-valid: Value '-1.0'.*\n"
+ + "Error: cvc-type.3.1.3: The value '-1.0' of element 'd:xdpi' is not valid.*");
+ }
+
+ public void testNegativeYdpi() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_YDPI, "-1");
+ checkFailure(replacements, "Error: cvc-minInclusive-valid: Value '-1'.*\n"
+ + "Error: cvc-type.3.1.3: The value '-1' of element 'd:ydpi' is not valid.*");
+
+ }
+
+ public void testNegativeDiagonalLength() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_DIAGONAL_LENGTH, "-1.0");
+
+ checkFailure(replacements, "Error: cvc-minInclusive-valid: Value '-1.0'.*\n"
+ + "Error: cvc-type.3.1.3: The value '-1.0' of element 'd:diagonal-length'.*");
+
+ }
+
+ public void testInvalidOpenGLVersion() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_GL_VERSION, "2");
+ checkFailure(replacements, "Error: cvc-pattern-valid: Value '2' is not facet-valid.*\n"
+ + "Error: cvc-type.3.1.3: The value '2' of element 'd:gl-version' is not valid.*");
+ }
+
+ public void testInvalidIconTypes() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_SIXTEEN, "extras/sixteen.jpeg");
+ replacements.put(DeviceSchema.NODE_SIXTY_FOUR, "extras/sixtyfour.jpeg");
+ replacements.put(DeviceSchema.NODE_PATH, "extras/frame.jpeg");
+ checkFailure(replacements, "Error: extras/sixtyfour.jpeg is not a valid file type.\n"
+ + "Error: extras/sixteen.jpeg is not a valid file type.\n"
+ + "Error: extras/frame.jpeg is not a valid file type.");
+ }
+
+ public void testMissingIcons() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_SIXTEEN, "extras/missing");
+ replacements.put(DeviceSchema.NODE_SIXTY_FOUR, "extras/missing");
+ replacements.put(DeviceSchema.NODE_PATH, "extras/missing");
+ checkFailure(replacements, "Error: extras/missing is not a valid path.\n"
+ + "Error: extras/missing is not a valid path.\n"
+ + "Error: extras/missing is not a valid path.");
+ }
+
+ public void testEmptyOpenGLExtensions() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_GL_EXTENSIONS, "");
+ checkSuccess(replacements);
+ }
+
+ public void testEmptySensors() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_SENSORS, "");
+ checkSuccess(replacements);
+ }
+
+ public void testEmptyNetworking() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_NETWORKING, "");
+ checkSuccess(replacements);
+ }
+
+ public void testEmptyCpu() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_CPU, "");
+ checkFailure(replacements, "Error: cvc-minLength-valid: Value '' with length = '0'.*\n"
+ + "Error: cvc-type.3.1.3: The value '' of element 'd:cpu' is not valid.*");
+ }
+
+ public void testEmptyGpu() throws Exception {
+ Map<String, String> replacements = new HashMap<String, String>();
+ replacements.put(DeviceSchema.NODE_GPU, "");
+ checkFailure(replacements, "Error: cvc-minLength-valid: Value '' with length = '0'.*\n"
+ + "Error: cvc-type.3.1.3: The value '' of element 'd:gpu' is not valid.*");
+ }
+
+ /**
+ * Reads in a valid devices XML file and if an element tag is in the
+ * replacements map, it replaces its text content with the corresponding
+ * value. Note this has no concept of namespaces or hierarchy, so it will
+ * replace the contents any and all elements with the specified tag name.
+ */
+ private static class ReplacementHandler extends DefaultHandler {
+ private Element mCurrElement = null;
+ private Document mDocument;
+ private final Stack<Element> mElementStack = new Stack<Element>();
+ private final Map<String, String> mPrefixes = new HashMap<String, String>();
+ private final Map<String, String> mReplacements;
+ private final StringBuilder mStringAccumulator = new StringBuilder();
+
+ public ReplacementHandler(Map<String, String> replacements) {
+ mReplacements = replacements;
+ }
+
+ @Override
+ public void startDocument() {
+ try {
+ mDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ } catch (ParserConfigurationException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String name, Attributes attributes) {
+ Element element = mDocument.createElement(name);
+ for (int i = 0; i < attributes.getLength(); i++) {
+ element.setAttribute(attributes.getQName(i), attributes.getValue(i));
+ }
+ for (String key : mPrefixes.keySet()) {
+ element.setAttribute(XMLConstants.XMLNS_ATTRIBUTE + ":" + key, mPrefixes.get(key));
+ }
+ mPrefixes.clear();
+ if (mCurrElement != null) {
+ mElementStack.push(mCurrElement);
+ }
+ mCurrElement = element;
+ }
+
+ @Override
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ mPrefixes.put(prefix, uri);
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ mStringAccumulator.append(ch, start, length);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String name) throws SAXException {
+ if (mReplacements.containsKey(localName)) {
+ mCurrElement.appendChild(mDocument.createTextNode(mReplacements.get(localName)));
+ } else {
+ String content = mStringAccumulator.toString().trim();
+ if (!content.isEmpty()) {
+ mCurrElement.appendChild(mDocument.createTextNode(content));
+ }
+ }
+
+ if (mElementStack.empty()) {
+ mDocument.appendChild(mCurrElement);
+ mCurrElement = null;
+ } else {
+ Element parent = mElementStack.pop();
+ parent.appendChild(mCurrElement);
+ mCurrElement = parent;
+ }
+ mStringAccumulator.setLength(0);
+ }
+
+ @Override
+ public void error(SAXParseException e) {
+ fail(e.getMessage());
+ }
+
+ @Override
+ public void fatalError(SAXParseException e) {
+ fail(e.getMessage());
+ }
+
+ public Document getGeneratedDocument() {
+ return mDocument;
+ }
+
+ }
+}
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices.xml
new file mode 100644
index 0000000..aeb0f04
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices.xml
@@ -0,0 +1,290 @@
+<?xml version="1.0"?>
+<d:devices
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:d="http://schemas.android.com/sdk/devices/1">
+
+ <d:device>
+ <d:name>
+ Galaxy Nexus
+ </d:name>
+ <d:manufacturer>
+ Samsung
+ </d:manufacturer>
+ <d:meta>
+ <d:icons>
+ <d:sixty-four>
+ extras/sixtyfour.png
+ </d:sixty-four>
+ <d:sixteen>
+ extras/sixteen.png
+ </d:sixteen>
+ </d:icons>
+ <d:frame>
+ <d:path>
+ extras/frame.png
+ </d:path>
+ <d:portrait-x-offset>0</d:portrait-x-offset>
+ <d:portrait-y-offset>0</d:portrait-y-offset>
+ <d:landscape-x-offset>0</d:landscape-x-offset>
+ <d:landscape-y-offset>0</d:landscape-y-offset>
+ </d:frame>
+ </d:meta>
+ <d:hardware>
+ <d:screen>
+ <d:screen-size>normal</d:screen-size>
+ <d:diagonal-length>4.65</d:diagonal-length> <!-- In inches -->
+ <d:pixel-density>xhdpi</d:pixel-density>
+ <d:screen-ratio>long</d:screen-ratio>
+ <d:dimensions>
+ <d:x-dimension>720</d:x-dimension>
+ <d:y-dimension>1280</d:y-dimension>
+ </d:dimensions>
+ <d:xdpi>316</d:xdpi>
+ <d:ydpi>316</d:ydpi>
+ <d:touch>
+ <d:multitouch>jazz-hands</d:multitouch>
+ <d:mechanism>finger</d:mechanism>
+ <d:screen-type>capacitive</d:screen-type>
+ </d:touch>
+ </d:screen>
+ <d:networking>
+ Bluetooth
+ Wifi
+ NFC
+ </d:networking>
+ <d:sensors>
+ Accelerometer
+ Barometer
+ Gyroscope
+ Compass
+ GPS
+ ProximitySensor
+ </d:sensors>
+ <d:mic>true</d:mic>
+ <d:camera>
+ <d:location>front</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>false</d:flash>
+ </d:camera>
+ <d:camera>
+ <d:location>back</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>true</d:flash>
+ </d:camera>
+ <d:keyboard>nokeys</d:keyboard>
+ <d:nav>nonav</d:nav>
+ <d:ram unit="GiB">1</d:ram>
+ <d:buttons>soft</d:buttons>
+ <d:internal-storage unit="GiB">16</d:internal-storage>
+ <d:removable-storage unit="KiB"></d:removable-storage>
+ <d:cpu>OMAP 4460</d:cpu> <!-- cpu type (Tegra3) freeform -->
+ <d:gpu>PowerVR SGX540</d:gpu>
+ <d:abi>
+ armeabi
+ armeabi-v7a
+ </d:abi>
+ <!--dock (car, desk, tv, none)-->
+ <d:dock>
+ </d:dock>
+ <!-- plugged in (never, charge, always) -->
+ <d:plugged-in>charge</d:plugged-in>
+ </d:hardware>
+ <d:software>
+ <d:api-level>14-</d:api-level>
+ <d:live-wallpaper-support>true</d:live-wallpaper-support>
+ <d:bluetooth-profiles>
+ HSP
+ HFP
+ SPP
+ A2DP
+ AVRCP
+ OPP
+ PBAP
+ GAVDP
+ AVDTP
+ HID
+ HDP
+ PAN
+ </d:bluetooth-profiles>
+ <d:gl-version>2.0</d:gl-version>
+ <!--
+ These can be gotten via
+ javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
+ -->
+ <d:gl-extensions>
+ GL_EXT_discard_framebuffer
+ GL_EXT_multi_draw_arrays
+ GL_EXT_shader_texture_lod
+ GL_EXT_texture_format_BGRA8888
+ GL_IMG_multisampled_render_to_texture
+ GL_IMG_program_binary
+ GL_IMG_read_format
+ GL_IMG_shader_binary
+ GL_IMG_texture_compression_pvrtc
+ GL_IMG_texture_format_BGRA8888
+ GL_IMG_texture_npot
+ GL_OES_compressed_ETC1_RGB8_texture
+ GL_OES_depth_texture
+ GL_OES_depth24
+ GL_OES_EGL_image
+ GL_OES_EGL_image_external
+ GL_OES_egl_sync
+ GL_OES_element_index_uint
+ GL_OES_fragment_precision_high
+ GL_OES_get_program_binary
+ GL_OES_mapbuffer
+ GL_OES_packed_depth_stencil
+ GL_OES_required_internalformat
+ GL_OES_rgb8_rgba8
+ GL_OES_standard_derivatives
+ GL_OES_texture_float
+ GL_OES_texture_half_float
+ GL_OES_vertex_array_object
+ GL_OES_vertex_half_float
+ </d:gl-extensions>
+ </d:software>
+ <d:state name="Portrait" default="true">
+ <d:description>The phone in portrait view</d:description>
+ <d:screen-orientation>portrait</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ <d:state name="Landscape">
+ <d:description>The phone in landscape view</d:description>
+ <d:screen-orientation>landscape</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ </d:device>
+ <d:device>
+ <d:name>Droid</d:name>
+ <d:manufacturer>Motorola</d:manufacturer>
+ <d:hardware>
+ <d:screen>
+ <d:screen-size>normal</d:screen-size>
+ <d:diagonal-length>3.7</d:diagonal-length>
+ <d:pixel-density>hdpi</d:pixel-density>
+ <d:screen-ratio>long</d:screen-ratio>
+ <d:dimensions>
+ <d:x-dimension>480</d:x-dimension>
+ <d:y-dimension>854</d:y-dimension>
+ </d:dimensions>
+ <d:xdpi>265</d:xdpi>
+ <d:ydpi>265</d:ydpi>
+ <d:touch>
+ <d:multitouch>distinct</d:multitouch>
+ <d:mechanism>finger</d:mechanism>
+ <d:screen-type>capacitive</d:screen-type>
+ </d:touch>
+ </d:screen>
+ <d:networking>
+ Bluetooth
+ Wifi
+ NFC
+ </d:networking>
+ <d:sensors>
+ Accelerometer
+ Barometer
+ Compass
+ GPS
+ ProximitySensor
+ LightSensor
+ </d:sensors>
+ <d:mic>true</d:mic>
+ <d:camera>
+ <d:location>back</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>true</d:flash>
+ </d:camera>
+ <d:keyboard>qwerty</d:keyboard>
+ <d:nav>dpad</d:nav>
+ <d:ram unit="MiB">256</d:ram>
+ <d:buttons>hard</d:buttons>
+ <d:internal-storage unit="MiB">512</d:internal-storage>
+ <d:removable-storage unit="GiB">16</d:removable-storage>
+ <d:cpu>OMAP 3430</d:cpu>
+ <d:gpu>PowerVR SGX 53</d:gpu>
+ <d:abi>
+ armeabi
+ armeabi-v7a
+ </d:abi>
+ <d:dock>
+ car
+ desk
+ </d:dock>
+ <d:plugged-in>charge</d:plugged-in>
+ </d:hardware>
+ <d:software>
+ <d:api-level>5-8</d:api-level>
+ <d:live-wallpaper-support>false</d:live-wallpaper-support>
+ <d:bluetooth-profiles>
+ GAP
+ SPP
+ HSP
+ HFP
+ A2DP
+ AVRCP
+ SDAP
+ </d:bluetooth-profiles>
+ <d:gl-version>1.1</d:gl-version>
+ <!--
+ These can be gotten via
+ javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
+ -->
+ <d:gl-extensions>
+ GL_OES_byte_coordinates
+ GL_OES_fixed_point
+ GL_OES_single_precision
+ GL_OES_matrix_get
+ GL_OES_read_format
+ GL_OES_compressed_paletted_texture
+ GL_OES_point_sprite
+ GL_OES_point_size_array
+ GL_OES_matrix_palette
+ GL_OES_draw_texture
+ GL_OES_query_matrix
+ GL_OES_texture_env_crossbar
+ GL_OES_texture_mirrored_repeat
+ GL_OES_texture_cube_map
+ GL_OES_blend_subtract
+ GL_OES_blend_func_separate
+ GL_OES_blend_equation_separate
+ GL_OES_stencil_wrap
+ GL_OES_extended_matrix_palette
+ GL_OES_framebuffer_object
+ GL_OES_rgb8_rgba8
+ GL_OES_depth24
+ GL_OES_stencil8
+ GL_OES_compressed_ETC1_RGB8_texture
+ GL_OES_mapbuffer
+ GL_OES_EGL_image
+ GL_EXT_multi_draw_arrays
+ GL_OES_required_internalformat
+ GL_IMG_read_format
+ GL_IMG_texture_compression_pvrtc
+ GL_IMG_texture_format_BGRA8888
+ GL_EXT_texture_format_BGRA8888
+ GL_IMG_texture_stream
+ GL_IMG_vertex_program
+ </d:gl-extensions>
+ </d:software>
+ <d:state name="Portrait" default="true">
+ <d:description>The phone in portrait view</d:description>
+ <d:screen-orientation>portrait</d:screen-orientation>
+ <d:keyboard-state>keyshidden</d:keyboard-state>
+ <d:nav-state>navhidden</d:nav-state>
+ </d:state>
+ <d:state name="Landscape, closed">
+ <d:description>The phone in landscape view with the keyboard closed</d:description>
+ <d:screen-orientation>landscape</d:screen-orientation>
+ <d:keyboard-state>keyshidden</d:keyboard-state>
+ <d:nav-state>navhidden</d:nav-state>
+ </d:state>
+ <d:state name="Landscape, open">
+ <d:description>The phone in landscape view with the keyboard open</d:description>
+ <d:screen-orientation>landscape</d:screen-orientation>
+ <d:keyboard-state>keysexposed</d:keyboard-state>
+ <d:nav-state>navexposed</d:nav-state>
+ </d:state>
+ </d:device>
+</d:devices>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml
new file mode 100644
index 0000000..71ab61a
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_minimal.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0"?>
+<d:devices
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:d="http://schemas.android.com/sdk/devices/1">
+
+ <d:device>
+ <d:name>
+ Galaxy Nexus
+ </d:name>
+ <d:manufacturer>
+ Samsung
+ </d:manufacturer>
+ <d:meta>
+ <d:icons>
+ <d:sixty-four>
+ extras/sixtyfour.png
+ </d:sixty-four>
+ <d:sixteen>
+ extras/sixteen.png
+ </d:sixteen>
+ </d:icons>
+ <d:frame>
+ <d:path>
+ extras/frame.png
+ </d:path>
+ <d:portrait-x-offset>0</d:portrait-x-offset>
+ <d:portrait-y-offset>0</d:portrait-y-offset>
+ <d:landscape-x-offset>0</d:landscape-x-offset>
+ <d:landscape-y-offset>0</d:landscape-y-offset>
+ </d:frame>
+ </d:meta>
+ <d:hardware>
+ <d:screen>
+ <d:screen-size>normal</d:screen-size>
+ <d:diagonal-length>4.65</d:diagonal-length> <!-- In inches -->
+ <d:pixel-density>xhdpi</d:pixel-density>
+ <d:screen-ratio>long</d:screen-ratio>
+ <d:dimensions>
+ <d:x-dimension>720</d:x-dimension>
+ <d:y-dimension>1280</d:y-dimension>
+ </d:dimensions>
+ <d:xdpi>316</d:xdpi>
+ <d:ydpi>316</d:ydpi>
+ <d:touch>
+ <d:multitouch>jazz-hands</d:multitouch>
+ <d:mechanism>finger</d:mechanism>
+ <d:screen-type>capacitive</d:screen-type>
+ </d:touch>
+ </d:screen>
+ <d:networking>
+ Bluetooth
+ Wifi
+ NFC
+ </d:networking>
+ <d:sensors>
+ Accelerometer
+ Barometer
+ Gyroscope
+ Compass
+ GPS
+ ProximitySensor
+ </d:sensors>
+ <d:mic>true</d:mic>
+ <d:camera>
+ <d:location>front</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>false</d:flash>
+ </d:camera>
+ <d:camera>
+ <d:location>back</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>true</d:flash>
+ </d:camera>
+ <d:keyboard>nokeys</d:keyboard>
+ <d:nav>nonav</d:nav>
+ <d:ram unit="GiB">1</d:ram>
+ <d:buttons>soft</d:buttons>
+ <d:internal-storage unit="GiB">16</d:internal-storage>
+ <d:removable-storage unit="KiB"></d:removable-storage>
+ <d:cpu>OMAP 4460</d:cpu> <!-- cpu type (Tegra3) freeform -->
+ <d:gpu>PowerVR SGX540</d:gpu>
+ <d:abi>
+ armeabi
+ armeabi-v7a
+ </d:abi>
+ <!--dock (car, desk, tv, none)-->
+ <d:dock>
+ </d:dock>
+ <!-- plugged in (never, charge, always) -->
+ <d:plugged-in>charge</d:plugged-in>
+ </d:hardware>
+ <d:software>
+ <d:api-level>15</d:api-level>
+ <d:live-wallpaper-support>true</d:live-wallpaper-support>
+ <d:bluetooth-profiles>
+ HSP
+ HFP
+ SPP
+ A2DP
+ AVRCP
+ OPP
+ PBAP
+ GAVDP
+ AVDTP
+ HID
+ HDP
+ PAN
+ </d:bluetooth-profiles>
+ <d:gl-version>2.0</d:gl-version>
+ <d:gl-extensions>
+ GL_EXT_discard_framebuffer
+ GL_EXT_multi_draw_arrays
+ GL_EXT_shader_texture_lod
+ GL_EXT_texture_format_BGRA8888
+ GL_IMG_multisampled_render_to_texture
+ GL_IMG_program_binary
+ GL_IMG_read_format
+ GL_IMG_shader_binary
+ GL_IMG_texture_compression_pvrtc
+ GL_IMG_texture_format_BGRA8888
+ GL_IMG_texture_npot
+ GL_OES_compressed_ETC1_RGB8_texture
+ GL_OES_depth_texture
+ GL_OES_depth24
+ GL_OES_EGL_image
+ GL_OES_EGL_image_external
+ GL_OES_egl_sync
+ GL_OES_element_index_uint
+ GL_OES_fragment_precision_high
+ GL_OES_get_program_binary
+ GL_OES_mapbuffer
+ GL_OES_packed_depth_stencil
+ GL_OES_required_internalformat
+ GL_OES_rgb8_rgba8
+ GL_OES_standard_derivatives
+ GL_OES_texture_float
+ GL_OES_texture_half_float
+ GL_OES_vertex_array_object
+ GL_OES_vertex_half_float
+ </d:gl-extensions>
+ </d:software>
+ <d:state name="Portrait" default="true">
+ <d:description>The phone in portrait view</d:description>
+ <d:screen-orientation>portrait</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ <d:state name="Landscape">
+ <d:description>The phone in landscape view</d:description>
+ <d:screen-orientation>landscape</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ </d:device>
+</d:devices>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml
new file mode 100644
index 0000000..3ebcedb
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_default.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0"?>
+<d:devices
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:d="http://schemas.android.com/sdk/devices/1">
+
+ <d:device>
+ <d:name>
+ Galaxy Nexus
+ </d:name>
+ <d:manufacturer>
+ Samsung
+ </d:manufacturer>
+ <d:hardware>
+ <d:screen>
+ <d:screen-size>normal</d:screen-size>
+ <d:diagonal-length>4.65</d:diagonal-length> <!-- In inches -->
+ <d:pixel-density>xhdpi</d:pixel-density>
+ <d:screen-ratio>long</d:screen-ratio>
+ <d:dimensions>
+ <d:x-dimension>720</d:x-dimension>
+ <d:y-dimension>1280</d:y-dimension>
+ </d:dimensions>
+ <d:xdpi>316</d:xdpi>
+ <d:ydpi>316</d:ydpi>
+ <d:touch>
+ <d:multitouch>jazz-hands</d:multitouch>
+ <d:mechanism>finger</d:mechanism>
+ <d:screen-type>capacitive</d:screen-type>
+ </d:touch>
+ </d:screen>
+ <d:networking>
+ Bluetooth
+ Wifi
+ NFC
+ </d:networking>
+ <d:sensors>
+ Accelerometer
+ Barometer
+ Gyroscope
+ Compass
+ GPS
+ ProximitySensor
+ </d:sensors>
+ <d:mic>true</d:mic>
+ <d:camera>
+ <d:location>front</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>false</d:flash>
+ </d:camera>
+ <d:camera>
+ <d:location>back</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>true</d:flash>
+ </d:camera>
+ <d:keyboard>nokeys</d:keyboard>
+ <d:nav>nonav</d:nav>
+ <d:ram unit="GiB">1</d:ram>
+ <d:buttons>soft</d:buttons>
+ <d:internal-storage unit="GiB">16</d:internal-storage>
+ <d:removable-storage unit="KiB"></d:removable-storage>
+ <d:cpu>OMAP 4460</d:cpu> <!-- cpu type (Tegra3) freeform -->
+ <d:gpu>PowerVR SGX540</d:gpu>
+ <d:abi>
+ armeabi
+ armeabi-v7a
+ </d:abi>
+ <!--dock (car, desk, tv, none)-->
+ <d:dock>
+ </d:dock>
+ <!-- plugged in (never, charge, always) -->
+ <d:plugged-in>charge</d:plugged-in>
+ </d:hardware>
+ <d:software>
+ <d:api-level>14</d:api-level>
+ <d:live-wallpaper-support>true</d:live-wallpaper-support>
+ <d:bluetooth-profiles>
+ HSP
+ HFP
+ SPP
+ A2DP
+ AVRCP
+ OPP
+ PBAP
+ GAVDP
+ AVDTP
+ HID
+ HDP
+ PAN
+ </d:bluetooth-profiles>
+ <d:gl-version>2.0</d:gl-version>
+ <!--
+ These can be gotten via
+ javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
+ -->
+ <d:gl-extensions>
+ GL_EXT_discard_framebuffer
+ GL_EXT_multi_draw_arrays
+ GL_EXT_shader_texture_lod
+ GL_EXT_texture_format_BGRA8888
+ GL_IMG_multisampled_render_to_texture
+ GL_IMG_program_binary
+ GL_IMG_read_format
+ GL_IMG_shader_binary
+ GL_IMG_texture_compression_pvrtc
+ GL_IMG_texture_format_BGRA8888
+ GL_IMG_texture_npot
+ GL_OES_compressed_ETC1_RGB8_texture
+ GL_OES_depth_texture
+ GL_OES_depth24
+ GL_OES_EGL_image
+ GL_OES_EGL_image_external
+ GL_OES_egl_sync
+ GL_OES_element_index_uint
+ GL_OES_fragment_precision_high
+ GL_OES_get_program_binary
+ GL_OES_mapbuffer
+ GL_OES_packed_depth_stencil
+ GL_OES_required_internalformat
+ GL_OES_rgb8_rgba8
+ GL_OES_standard_derivatives
+ GL_OES_texture_float
+ GL_OES_texture_half_float
+ GL_OES_vertex_array_object
+ GL_OES_vertex_half_float
+ </d:gl-extensions>
+ </d:software>
+ <d:state name="Portrait">
+ <d:description>The phone in portrait view</d:description>
+ <d:screen-orientation>portrait</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ </d:device>
+</d:devices>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml
new file mode 100644
index 0000000..a5c3da1
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_hardware.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<d:devices
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:d="http://schemas.android.com/sdk/devices/1">
+
+ <d:device>
+ <d:name>
+ Galaxy Nexus
+ </d:name>
+ <d:manufacturer>
+ Samsung
+ </d:manufacturer>
+ <d:software>
+ <d:api-level>14</d:api-level>
+ <d:live-wallpaper-support>true</d:live-wallpaper-support>
+ <d:bluetooth-profiles>
+ HSP
+ HFP
+ SPP
+ A2DP
+ AVRCP
+ OPP
+ PBAP
+ GAVDP
+ AVDTP
+ HID
+ HDP
+ PAN
+ </d:bluetooth-profiles>
+ <d:gl-version>2.0</d:gl-version>
+ <!--
+ These can be gotten via
+ javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
+ -->
+ <d:gl-extensions>
+ GL_EXT_discard_framebuffer
+ GL_EXT_multi_draw_arrays
+ GL_EXT_shader_texture_lod
+ GL_EXT_texture_format_BGRA8888
+ GL_IMG_multisampled_render_to_texture
+ GL_IMG_program_binary
+ GL_IMG_read_format
+ GL_IMG_shader_binary
+ GL_IMG_texture_compression_pvrtc
+ GL_IMG_texture_format_BGRA8888
+ GL_IMG_texture_npot
+ GL_OES_compressed_ETC1_RGB8_texture
+ GL_OES_depth_texture
+ GL_OES_depth24
+ GL_OES_EGL_image
+ GL_OES_EGL_image_external
+ GL_OES_egl_sync
+ GL_OES_element_index_uint
+ GL_OES_fragment_precision_high
+ GL_OES_get_program_binary
+ GL_OES_mapbuffer
+ GL_OES_packed_depth_stencil
+ GL_OES_required_internalformat
+ GL_OES_rgb8_rgba8
+ GL_OES_standard_derivatives
+ GL_OES_texture_float
+ GL_OES_texture_half_float
+ GL_OES_vertex_array_object
+ GL_OES_vertex_half_float
+ </d:gl-extensions>
+ </d:software>
+ <d:state name="Portrait" default="true">
+ <d:description>The phone in portrait view</d:description>
+ <d:screen-orientation>portrait</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ <d:state name="Landscape">
+ <d:description>The phone in landscape view</d:description>
+ <d:screen-orientation>landscape</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ </d:device>
+</d:devices>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_software.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_software.xml
new file mode 100644
index 0000000..899110a
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_software.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<d:devices
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:d="http://schemas.android.com/sdk/devices/1">
+
+ <d:device>
+ <d:name>
+ Galaxy Nexus
+ </d:name>
+ <d:manufacturer>
+ Samsung
+ </d:manufacturer>
+ <d:hardware>
+ <d:screen>
+ <d:screen-size>normal</d:screen-size>
+ <d:diagonal-length>4.65</d:diagonal-length> <!-- In inches -->
+ <d:pixel-density>xhdpi</d:pixel-density>
+ <d:screen-ratio>long</d:screen-ratio>
+ <d:dimensions>
+ <d:x-dimension>720</d:x-dimension>
+ <d:y-dimension>1280</d:y-dimension>
+ </d:dimensions>
+ <d:xdpi>316</d:xdpi>
+ <d:ydpi>316</d:ydpi>
+ <d:touch>
+ <d:multitouch>jazz-hands</d:multitouch>
+ <d:mechanism>finger</d:mechanism>
+ <d:screen-type>capacitive</d:screen-type>
+ </d:touch>
+ </d:screen>
+ <d:networking>
+ Bluetooth
+ Wifi
+ NFC
+ </d:networking>
+ <d:sensors>
+ Accelerometer
+ Barometer
+ Gyroscope
+ Compass
+ GPS
+ ProximitySensor
+ </d:sensors>
+ <d:mic>true</d:mic>
+ <d:camera>
+ <d:location>front</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>false</d:flash>
+ </d:camera>
+ <d:camera>
+ <d:location>back</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>true</d:flash>
+ </d:camera>
+ <d:keyboard>nokeys</d:keyboard>
+ <d:nav>nonav</d:nav>
+ <d:ram unit="GiB">1</d:ram>
+ <d:buttons>soft</d:buttons>
+ <d:internal-storage unit="GiB">16</d:internal-storage>
+ <d:removable-storage unit="KiB"></d:removable-storage>
+ <d:cpu>OMAP 4460</d:cpu> <!-- cpu type (Tegra3) freeform -->
+ <d:gpu>PowerVR SGX540</d:gpu>
+ <d:abi>
+ armeabi
+ armeabi-v7a
+ </d:abi>
+ <!--dock (car, desk, tv, none)-->
+ <d:dock>
+ </d:dock>
+ <!-- plugged in (never, charge, always) -->
+ <d:plugged-in>charge</d:plugged-in>
+ </d:hardware>
+ <d:state name="Portrait" default="true">
+ <d:description>The phone in portrait view</d:description>
+ <d:screen-orientation>portrait</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ </d:device>
+</d:devices>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml
new file mode 100644
index 0000000..c4955b4
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_no_states.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0"?>
+<d:devices
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:d="http://schemas.android.com/sdk/devices/1">
+
+ <d:device>
+ <d:name>
+ Galaxy Nexus
+ </d:name>
+ <d:manufacturer>
+ Samsung
+ </d:manufacturer>
+ <d:hardware>
+ <d:screen>
+ <d:screen-size>normal</d:screen-size>
+ <d:diagonal-length>4.65</d:diagonal-length> <!-- In inches -->
+ <d:pixel-density>xhdpi</d:pixel-density>
+ <d:screen-ratio>long</d:screen-ratio>
+ <d:dimensions>
+ <d:x-dimension>720</d:x-dimension>
+ <d:y-dimension>1280</d:y-dimension>
+ </d:dimensions>
+ <d:xdpi>316</d:xdpi>
+ <d:ydpi>316</d:ydpi>
+ <d:touch>
+ <d:multitouch>jazz-hands</d:multitouch>
+ <d:mechanism>finger</d:mechanism>
+ <d:screen-type>capacitive</d:screen-type>
+ </d:touch>
+ </d:screen>
+ <d:networking>
+ Bluetooth
+ Wifi
+ NFC
+ </d:networking>
+ <d:sensors>
+ Accelerometer
+ Barometer
+ Gyroscope
+ Compass
+ GPS
+ ProximitySensor
+ </d:sensors>
+ <d:mic>true</d:mic>
+ <d:camera>
+ <d:location>front</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>false</d:flash>
+ </d:camera>
+ <d:camera>
+ <d:location>back</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>true</d:flash>
+ </d:camera>
+ <d:keyboard>nokeys</d:keyboard>
+ <d:nav>nonav</d:nav>
+ <d:ram unit="GiB">1</d:ram>
+ <d:buttons>soft</d:buttons>
+ <d:internal-storage unit="GiB">16</d:internal-storage>
+ <d:removable-storage unit="KiB"></d:removable-storage>
+ <d:cpu>OMAP 4460</d:cpu> <!-- cpu type (Tegra3) freeform -->
+ <d:gpu>PowerVR SGX540</d:gpu>
+ <d:abi>
+ armeabi
+ armeabi-v7a
+ </d:abi>
+ <!--dock (car, desk, tv, none)-->
+ <d:dock>
+ </d:dock>
+ <!-- plugged in (never, charge, always) -->
+ <d:plugged-in>charge</d:plugged-in>
+ </d:hardware>
+ <d:software>
+ <d:api-level>14</d:api-level>
+ <d:live-wallpaper-support>true</d:live-wallpaper-support>
+ <d:bluetooth-profiles>
+ HSP
+ HFP
+ SPP
+ A2DP
+ AVRCP
+ OPP
+ PBAP
+ GAVDP
+ AVDTP
+ HID
+ HDP
+ PAN
+ </d:bluetooth-profiles>
+ <d:gl-version>2.0</d:gl-version>
+ <!--
+ These can be gotten via
+ javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
+ -->
+ <d:gl-extensions>
+ GL_EXT_discard_framebuffer
+ GL_EXT_multi_draw_arrays
+ GL_EXT_shader_texture_lod
+ GL_EXT_texture_format_BGRA8888
+ GL_IMG_multisampled_render_to_texture
+ GL_IMG_program_binary
+ GL_IMG_read_format
+ GL_IMG_shader_binary
+ GL_IMG_texture_compression_pvrtc
+ GL_IMG_texture_format_BGRA8888
+ GL_IMG_texture_npot
+ GL_OES_compressed_ETC1_RGB8_texture
+ GL_OES_depth_texture
+ GL_OES_depth24
+ GL_OES_EGL_image
+ GL_OES_EGL_image_external
+ GL_OES_egl_sync
+ GL_OES_element_index_uint
+ GL_OES_fragment_precision_high
+ GL_OES_get_program_binary
+ GL_OES_mapbuffer
+ GL_OES_packed_depth_stencil
+ GL_OES_required_internalformat
+ GL_OES_rgb8_rgba8
+ GL_OES_standard_derivatives
+ GL_OES_texture_float
+ GL_OES_texture_half_float
+ GL_OES_vertex_array_object
+ GL_OES_vertex_half_float
+ </d:gl-extensions>
+ </d:software>
+ </d:device>
+</d:devices>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml b/device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml
new file mode 100644
index 0000000..a4e464c
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/devices_too_many_defaults.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0"?>
+<d:devices
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:d="http://schemas.android.com/sdk/devices/1">
+
+ <d:device>
+ <d:name>
+ Galaxy Nexus
+ </d:name>
+ <d:manufacturer>
+ Samsung
+ </d:manufacturer>
+ <d:hardware>
+ <d:screen>
+ <d:screen-size>normal</d:screen-size>
+ <d:diagonal-length>4.65</d:diagonal-length> <!-- In inches -->
+ <d:pixel-density>xhdpi</d:pixel-density>
+ <d:screen-ratio>long</d:screen-ratio>
+ <d:dimensions>
+ <d:x-dimension>720</d:x-dimension>
+ <d:y-dimension>1280</d:y-dimension>
+ </d:dimensions>
+ <d:xdpi>316</d:xdpi>
+ <d:ydpi>316</d:ydpi>
+ <d:touch>
+ <d:multitouch>jazz-hands</d:multitouch>
+ <d:mechanism>finger</d:mechanism>
+ <d:screen-type>capacitive</d:screen-type>
+ </d:touch>
+ </d:screen>
+ <d:networking>
+ Bluetooth
+ Wifi
+ NFC
+ </d:networking>
+ <d:sensors>
+ Accelerometer
+ Barometer
+ Gyroscope
+ Compass
+ GPS
+ ProximitySensor
+ </d:sensors>
+ <d:mic>true</d:mic>
+ <d:camera>
+ <d:location>front</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>false</d:flash>
+ </d:camera>
+ <d:camera>
+ <d:location>back</d:location>
+ <d:autofocus>true</d:autofocus>
+ <d:flash>true</d:flash>
+ </d:camera>
+ <d:keyboard>nokeys</d:keyboard>
+ <d:nav>nonav</d:nav>
+ <d:ram unit="GiB">1</d:ram>
+ <d:buttons>soft</d:buttons>
+ <d:internal-storage unit="GiB">16</d:internal-storage>
+ <d:removable-storage unit="KiB"></d:removable-storage>
+ <d:cpu>OMAP 4460</d:cpu> <!-- cpu type (Tegra3) freeform -->
+ <d:gpu>PowerVR SGX540</d:gpu>
+ <d:abi>
+ armeabi
+ armeabi-v7a
+ </d:abi>
+ <!--dock (car, desk, tv, none)-->
+ <d:dock>
+ </d:dock>
+ <!-- plugged in (never, charge, always) -->
+ <d:plugged-in>charge</d:plugged-in>
+ </d:hardware>
+ <d:software>
+ <d:api-level>14</d:api-level>
+ <d:live-wallpaper-support>true</d:live-wallpaper-support>
+ <d:bluetooth-profiles>
+ HSP
+ HFP
+ SPP
+ A2DP
+ AVRCP
+ OPP
+ PBAP
+ GAVDP
+ AVDTP
+ HID
+ HDP
+ PAN
+ </d:bluetooth-profiles>
+ <d:gl-version>2.0</d:gl-version>
+ <!--
+ These can be gotten via
+ javax.microedition.khronos.opengles.GL10.glGetString(GL10.GL_EXTENSIONS);
+ -->
+ <d:gl-extensions>
+ GL_EXT_discard_framebuffer
+ GL_EXT_multi_draw_arrays
+ GL_EXT_shader_texture_lod
+ GL_EXT_texture_format_BGRA8888
+ GL_IMG_multisampled_render_to_texture
+ GL_IMG_program_binary
+ GL_IMG_read_format
+ GL_IMG_shader_binary
+ GL_IMG_texture_compression_pvrtc
+ GL_IMG_texture_format_BGRA8888
+ GL_IMG_texture_npot
+ GL_OES_compressed_ETC1_RGB8_texture
+ GL_OES_depth_texture
+ GL_OES_depth24
+ GL_OES_EGL_image
+ GL_OES_EGL_image_external
+ GL_OES_egl_sync
+ GL_OES_element_index_uint
+ GL_OES_fragment_precision_high
+ GL_OES_get_program_binary
+ GL_OES_mapbuffer
+ GL_OES_packed_depth_stencil
+ GL_OES_required_internalformat
+ GL_OES_rgb8_rgba8
+ GL_OES_standard_derivatives
+ GL_OES_texture_float
+ GL_OES_texture_half_float
+ GL_OES_vertex_array_object
+ GL_OES_vertex_half_float
+ </d:gl-extensions>
+ </d:software>
+ <d:state name="Portrait" default="true">
+ <d:description>The phone in portrait view</d:description>
+ <d:screen-orientation>portrait</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ <d:state name="Landscape" default="true">
+ <d:description>The phone in landscape view</d:description>
+ <d:screen-orientation>landscape</d:screen-orientation>
+ <d:keyboard-state>keyssoft</d:keyboard-state>
+ <d:nav-state>nonav</d:nav-state>
+ </d:state>
+ </d:device>
+</d:devices>
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/extras/frame.jpeg b/device_validator/dvlib/tests/src/com/android/dvlib/extras/frame.jpeg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/extras/frame.jpeg
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/extras/frame.png b/device_validator/dvlib/tests/src/com/android/dvlib/extras/frame.png
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/extras/frame.png
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixteen.jpeg b/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixteen.jpeg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixteen.jpeg
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixteen.png b/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixteen.png
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixteen.png
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixtyfour.jpeg b/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixtyfour.jpeg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixtyfour.jpeg
diff --git a/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixtyfour.png b/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixtyfour.png
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/device_validator/dvlib/tests/src/com/android/dvlib/extras/sixtyfour.png
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseViewRule.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseViewRule.java
index 4cc5f5e..2c9dcbe 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseViewRule.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/BaseViewRule.java
@@ -194,7 +194,11 @@ public class BaseViewRule extends AbstractViewRule {
// Strip off the @id prefix stuff
String oldId = node.getStringAttr(ANDROID_URI, ATTR_ID);
oldId = stripIdPrefix(ensureValidString(oldId));
- IValidator validator = mRulesEngine.getResourceValidator();
+ IValidator validator = mRulesEngine.getResourceValidator("id",//$NON-NLS-1$
+ false /*uniqueInProject*/,
+ true /*uniqueInLayout*/,
+ false /*exists*/,
+ oldId);
String newId = mRulesEngine.displayInput("New Id:", oldId, validator);
if (newId != null && newId.trim().length() > 0) {
if (!newId.startsWith(NEW_ID_PREFIX)) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
index b002ff5..f360e23 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
@@ -49,7 +49,7 @@ public final class VersionCheck {
/**
* The minimum version of the SDK Tools that this version of ADT requires.
*/
- private final static FullRevision MIN_TOOLS_REV = new FullRevision(17);
+ private final static FullRevision MIN_TOOLS_REV = new FullRevision(20);
/**
* Pattern to get the minimum plugin version supported by the SDK. This is read from
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptParser.java
index 3b9d136..5742888 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptParser.java
@@ -150,11 +150,22 @@ public final class AaptParser {
/**
* Error message emitted when aapt skips a file because for example it's name is
* invalid, such as a layout file name which starts with _.
+ * <p>
+ * This error message is used by AAPT in Tools 19 and earlier.
*/
private static final Pattern sSkippingPattern =
Pattern.compile(" \\(skipping (.+) .+ '(.*)'\\)"); //$NON-NLS-1$
/**
+ * Error message emitted when aapt skips a file because for example it's name is
+ * invalid, such as a layout file name which starts with _.
+ * <p>
+ * This error message is used by AAPT in Tools 20 and later.
+ */
+ private static final Pattern sNewSkippingPattern =
+ Pattern.compile(" \\(skipping .+ '(.+)' due to ANDROID_AAPT_IGNORE pattern '.+'\\)"); //$NON-NLS-1$
+
+ /**
* Suffix of error message which points to the first occurrence of a repeated resource
* definition.
* Example:
@@ -409,6 +420,25 @@ public final class AaptParser {
continue;
}
+ m = sNewSkippingPattern.matcher(p);
+ if (m.matches()) {
+ String location = m.group(1);
+
+ if (location.startsWith(".") //$NON-NLS-1$
+ || location.endsWith("~")) { //$NON-NLS-1$
+ continue;
+ }
+
+ // check the values and attempt to mark the file.
+ if (checkAndMark(location, null, p.trim(), osRoot, project,
+ AdtConstants.MARKER_AAPT_COMPILE, IMarker.SEVERITY_WARNING) == false) {
+ return true;
+ }
+
+ // success, go to the next line
+ continue;
+ }
+
m = sSkippingPattern.matcher(p);
if (m.matches()) {
String location = m.group(2);
@@ -424,7 +454,7 @@ public final class AaptParser {
// check the values and attempt to mark the file.
if (checkAndMark(location, null, p.trim(), osRoot, project,
- AdtConstants.MARKER_AAPT_COMPILE, IMarker.SEVERITY_ERROR) == false) {
+ AdtConstants.MARKER_AAPT_COMPILE, IMarker.SEVERITY_WARNING) == false) {
return true;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
index 396e172..2f3e0b1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
@@ -27,14 +27,12 @@ import com.android.ide.eclipse.adt.internal.lint.EclipseLintRunner;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.Sdk;
-import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener;
import com.android.ide.eclipse.adt.internal.sdk.Sdk.TargetChangeListener;
import com.android.sdklib.IAndroidTarget;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.ResourcesPlugin;
@@ -71,11 +69,9 @@ import org.eclipse.ui.forms.editor.IFormPage;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.events.IHyperlinkListener;
-import org.eclipse.ui.forms.widgets.FormText;
+import org.eclipse.ui.ide.IDEActionFactory;
import org.eclipse.ui.ide.IGotoMarker;
import org.eclipse.ui.internal.browser.WorkbenchBrowserSupport;
-import org.eclipse.ui.part.MultiPageEditorPart;
-import org.eclipse.ui.part.WorkbenchPart;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
@@ -365,6 +361,21 @@ public abstract class AndroidXmlEditor extends FormEditor implements IResourceCh
action = mTextEditor.getAction(ActionFactory.REDO.getId());
bars.setGlobalActionHandler(ActionFactory.REDO.getId(), action);
+ bars.setGlobalActionHandler(ActionFactory.DELETE.getId(),
+ mTextEditor.getAction(ActionFactory.DELETE.getId()));
+ bars.setGlobalActionHandler(ActionFactory.CUT.getId(),
+ mTextEditor.getAction(ActionFactory.CUT.getId()));
+ bars.setGlobalActionHandler(ActionFactory.COPY.getId(),
+ mTextEditor.getAction(ActionFactory.COPY.getId()));
+ bars.setGlobalActionHandler(ActionFactory.PASTE.getId(),
+ mTextEditor.getAction(ActionFactory.PASTE.getId()));
+ bars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),
+ mTextEditor.getAction(ActionFactory.SELECT_ALL.getId()));
+ bars.setGlobalActionHandler(ActionFactory.FIND.getId(),
+ mTextEditor.getAction(ActionFactory.FIND.getId()));
+ bars.setGlobalActionHandler(IDEActionFactory.BOOKMARK.getId(),
+ mTextEditor.getAction(IDEActionFactory.BOOKMARK.getId()));
+
bars.updateActionBars();
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/common/CommonXmlEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/common/CommonXmlEditor.java
index 5ee76c2..a7b3660 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/common/CommonXmlEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/common/CommonXmlEditor.java
@@ -42,7 +42,6 @@ import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.ISourceViewerExtension2;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IShowEditorInput;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinter.java
index 22a86af..a5e26bf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinter.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinter.java
@@ -752,6 +752,10 @@ public class XmlPrettyPrinter {
return false;
}
+ if (isMarkupElement(element)) {
+ return false;
+ }
+
// See if this element should be separated from the previous element.
// This is the case if we are not compressing whitespace (checked above),
// or if we are not immediately following a comment (in which case the
@@ -876,14 +880,36 @@ public class XmlPrettyPrinter {
return false;
}
+ if (isMarkupElement(element)) {
+ return false;
+ }
+
return element.getParentNode().getNodeType() == Node.ELEMENT_NODE
&& !keepElementAsSingleLine(depth - 1, (Element) element.getParentNode());
}
private boolean isMarkupElement(Element element) {
- // <u>, <b>, <i>, ...
- // http://developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling
- return mStyle == XmlFormatStyle.RESOURCE && element.getTagName().length() == 1;
+ // The documentation suggests that the allowed tags are <u>, <b> and <i>:
+ // developer.android.com/guide/topics/resources/string-resource.html#FormattingAndStyling
+ // However, the full set of tags accepted by Html.fromHtml is much larger. Therefore,
+ // instead consider *any* element nested inside a <string> definition to be a markup
+ // element. See frameworks/base/core/java/android/text/Html.java and look for
+ // HtmlToSpannedConverter#handleStartTag.
+
+ if (mStyle != XmlFormatStyle.RESOURCE) {
+ return false;
+ }
+
+ Node curr = element.getParentNode();
+ while (curr != null) {
+ if (STRING_ELEMENT.equals(curr.getNodeName())) {
+ return true;
+ }
+
+ curr = curr.getParentNode();
+ }
+
+ return false;
}
/**
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
index 9830f7e..a22b29a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
@@ -15,10 +15,10 @@
*/
package com.android.ide.eclipse.adt.internal.editors.layout.gle2;
-import static com.android.util.XmlUtils.ANDROID_URI;
import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
import static com.android.ide.common.layout.LayoutConstants.ID_PREFIX;
import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX;
+import static com.android.util.XmlUtils.ANDROID_URI;
import static org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML.ContentTypeID_XML;
import com.android.annotations.NonNull;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
index 287a192..addb8bd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/GraphicalEditorPart.java
@@ -1563,6 +1563,9 @@ public class GraphicalEditorPart extends EditorPart
return null;
}
+ if (mConfigComposite.isDisposed()) {
+ return null;
+ }
assert mConfigComposite.getDisplay().getThread() == Thread.currentThread();
// attempt to get a target from the configuration selector.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
index e793983..8337007 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
@@ -16,10 +16,13 @@
package com.android.ide.eclipse.adt.internal.editors.layout.gre;
+import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
+import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX;
import static com.android.sdklib.SdkConstants.CLASS_FRAGMENT;
import static com.android.sdklib.SdkConstants.CLASS_V4_FRAGMENT;
import static com.android.tools.lint.detector.api.LintConstants.AUTO_URI;
import static com.android.tools.lint.detector.api.LintConstants.URI_PREFIX;
+import static com.android.util.XmlUtils.ANDROID_URI;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
@@ -30,6 +33,7 @@ import com.android.ide.common.api.IViewMetadata;
import com.android.ide.common.api.IViewRule;
import com.android.ide.common.api.Margins;
import com.android.ide.common.api.Rect;
+import com.android.ide.common.layout.BaseViewRule;
import com.android.ide.common.resources.ResourceRepository;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.actions.AddCompatibilityJarAction;
@@ -45,6 +49,7 @@ import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo;
import com.android.ide.eclipse.adt.internal.editors.uimodel.UiDocumentNode;
import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.resources.CyclicDependencyValidator;
+import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator;
import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
@@ -91,11 +96,17 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.SelectionDialog;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -208,14 +219,65 @@ class ClientRulesEngine implements IClientRulesEngine {
}
@Override
- public @Nullable IValidator getResourceValidator() {
- //return ResourceNameValidator.create(false, mRulesEngine.getEditor().getProject(),
- // ResourceType.ID);
- return null;
+ public IValidator getResourceValidator(
+ @NonNull final String resourceTypeName, final boolean uniqueInProject,
+ final boolean uniqueInLayout, final boolean exists, final String... allowed) {
+ return new IValidator() {
+ private ResourceNameValidator mValidator;
+
+ @Override
+ public String validate(@NonNull String text) {
+ if (mValidator == null) {
+ ResourceType type = ResourceType.getEnum(resourceTypeName);
+ if (uniqueInLayout) {
+ assert !uniqueInProject;
+ assert !exists;
+ Set<String> existing = new HashSet<String>();
+ Document doc = mRulesEngine.getEditor().getModel().getXmlDocument();
+ if (doc != null) {
+ addIds(doc, existing);
+ }
+ for (String s : allowed) {
+ existing.remove(s);
+ }
+ mValidator = ResourceNameValidator.create(false, existing, type);
+ } else {
+ assert allowed.length == 0;
+ IProject project = mRulesEngine.getEditor().getProject();
+ mValidator = ResourceNameValidator.create(false, project, type);
+ if (uniqueInProject) {
+ mValidator.unique();
+ }
+ }
+ if (exists) {
+ mValidator.exist();
+ }
+ }
+
+ return mValidator.isValid(text);
+ }
+ };
+ }
+
+ /** Find declared ids under the given DOM node */
+ private static void addIds(Node node, Set<String> ids) {
+ if (node.getNodeType() == Node.ELEMENT_NODE) {
+ Element element = (Element) node;
+ String id = element.getAttributeNS(ANDROID_URI, ATTR_ID);
+ if (id != null && id.startsWith(NEW_ID_PREFIX)) {
+ ids.add(BaseViewRule.stripIdPrefix(id));
+ }
+ }
+
+ NodeList children = node.getChildNodes();
+ for (int i = 0, n = children.getLength(); i < n; i++) {
+ Node child = children.item(i);
+ addIds(child, ids);
+ }
}
@Override
- public String displayReferenceInput(String currentValue) {
+ public String displayReferenceInput(@Nullable String currentValue) {
GraphicalEditorPart graphicalEditor = mRulesEngine.getEditor();
LayoutEditorDelegate delegate = graphicalEditor.getEditorDelegate();
IProject project = delegate.getEditor().getProject();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java
index 657c9ec..f753408 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/ExtractIncludeRefactoring.java
@@ -16,7 +16,6 @@
package com.android.ide.eclipse.adt.internal.editors.layout.refactoring;
import static com.android.AndroidConstants.FD_RES_LAYOUT;
-import static com.android.util.XmlUtils.ANDROID_URI;
import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_HEIGHT;
import static com.android.ide.common.layout.LayoutConstants.ATTR_LAYOUT_PREFIX;
@@ -30,6 +29,7 @@ import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP;
import static com.android.resources.ResourceType.LAYOUT;
import static com.android.sdklib.SdkConstants.FD_RES;
import static com.android.util.XmlUtils.ANDROID_NS_NAME;
+import static com.android.util.XmlUtils.ANDROID_URI;
import static com.android.util.XmlUtils.XMLNS;
import static com.android.util.XmlUtils.XMLNS_COLON;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java
index 147327d..57a85e8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/lint/LintListDialog.java
@@ -72,6 +72,7 @@ class LintListDialog extends TitleAreaDialog implements SelectionListener {
super(parentShell);
mFile = file;
mEditor = editor;
+ setHelpAvailable(false);
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java
index 6266ea6..3be2f96 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.adt.internal.project;
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtConstants;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.sdklib.SdkConstants;
@@ -393,7 +395,7 @@ public final class BaseProjectHelper {
* @param filter an optional filter to control which android project are returned. Can be null.
* @return an array of IJavaProject, which can be empty if no projects match.
*/
- public static IJavaProject[] getAndroidProjects(IProjectFilter filter) {
+ public static @NonNull IJavaProject[] getAndroidProjects(@Nullable IProjectFilter filter) {
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IJavaModel javaModel = JavaCore.create(workspaceRoot);
@@ -408,7 +410,9 @@ public final class BaseProjectHelper {
* @param filter an optional filter to control which android project are returned. Can be null.
* @return an array of IJavaProject, which can be empty if no projects match.
*/
- public static IJavaProject[] getAndroidProjects(IJavaModel javaModel, IProjectFilter filter) {
+ @NonNull
+ public static IJavaProject[] getAndroidProjects(@NonNull IJavaModel javaModel,
+ @Nullable IProjectFilter filter) {
// get the java projects
IJavaProject[] javaProjectList = null;
try {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
index 188bbc7..5208ed8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidator.java
@@ -42,6 +42,12 @@ public class ResourceNameValidator implements IInputValidator {
/** Set of existing names to check for conflicts with */
private Set<String> mExisting;
+ /** If true, the validated name must be unique */
+ private boolean mUnique = true;
+
+ /** If true, the validated name must exist */
+ private boolean mExist;
+
/**
* True if the resource name being considered is a "file" based resource (where the
* resource name is the actual file name, rather than just a value attribute inside an
@@ -65,6 +71,30 @@ public class ResourceNameValidator implements IInputValidator {
mIsImageType = isImageType;
}
+ /**
+ * Makes the resource name validator require that names are unique.
+ *
+ * @return this, for construction chaining
+ */
+ public ResourceNameValidator unique() {
+ mUnique = true;
+ mExist = false;
+
+ return this;
+ }
+
+ /**
+ * Makes the resource name validator require that names already exist
+ *
+ * @return this, for construction chaining
+ */
+ public ResourceNameValidator exist() {
+ mExist = true;
+ mUnique = false;
+
+ return this;
+ }
+
@Override
public String isValid(String newText) {
// IValidator has the same interface as SWT's IInputValidator
@@ -130,8 +160,14 @@ public class ResourceNameValidator implements IInputValidator {
return String.format("%1$s is not a valid name (reserved Java keyword)", newText);
}
- if (mExisting != null && mExisting.contains(newText)) {
- return String.format("%1$s already exists", newText);
+
+ if (mExisting != null && (mUnique || mExist)) {
+ boolean exists = mExisting.contains(newText);
+ if (mUnique && exists) {
+ return String.format("%1$s already exists", newText);
+ } else if (mExist && !exists) {
+ return String.format("%1$s does not exist", newText);
+ }
}
return null;
@@ -170,11 +206,12 @@ public class ResourceNameValidator implements IInputValidator {
ResourceType type) {
boolean isFileType = ResourceHelper.isFileBasedResourceType(type);
return new ResourceNameValidator(allowXmlExtension, existing, isFileType,
- type == ResourceType.DRAWABLE);
+ type == ResourceType.DRAWABLE).unique();
}
/**
- * Creates a new {@link ResourceNameValidator}
+ * Creates a new {@link ResourceNameValidator}. By default, the name will need to be
+ * unique in the project.
*
* @param allowXmlExtension if true, allow .xml to be entered as a suffix for the
* resource name
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
index 7b90633..d2747a9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
@@ -21,6 +21,7 @@ import static com.android.ide.common.resources.ResourceResolver.PREFIX_ANDROID_R
import static com.android.ide.common.resources.ResourceResolver.PREFIX_RESOURCE_REF;
import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.resources.ResourceItem;
import com.android.ide.common.resources.ResourceRepository;
@@ -367,15 +368,19 @@ public class ResourceChooser extends AbstractElementListSelectionDialog implemen
} else {
if (ResourceHelper.isValueBasedResourceType(mResourceType)) {
String newName = createNewValue(mResourceType);
- selectAddedItem(newName);
+ if (newName != null) {
+ selectAddedItem(newName);
+ }
} else {
String newName = createNewFile(mResourceType);
- selectAddedItem(newName);
+ if (newName != null) {
+ selectAddedItem(newName);
+ }
}
}
}
- private void selectAddedItem(String newName) {
+ private void selectAddedItem(@NonNull String newName) {
// Recompute the "current resource" to select the new id
ResourceItem[] items = setupResourceList();
@@ -506,6 +511,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog implemen
}
}
+ @Nullable
private String createNewFile(ResourceType type) {
// Show a name/value dialog entering the key name and the value
Shell shell = AdtPlugin.getDisplay().getActiveShell();
@@ -538,6 +544,7 @@ public class ResourceChooser extends AbstractElementListSelectionDialog implemen
}
+ @Nullable
private String createNewValue(ResourceType type) {
// Show a name/value dialog entering the key name and the value
Shell shell = AdtPlugin.getDisplay().getActiveShell();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java
index 9a61b4f..d9f650c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/ActivityPage.java
@@ -15,12 +15,12 @@
*/
package com.android.ide.eclipse.adt.internal.wizards.templates;
-import static com.android.ide.eclipse.adt.internal.wizards.templates.NewTemplateWizard.ACTIVITY_TEMPLATES;
import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_PADDING;
import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_WIDTH;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageControl;
+import com.google.common.io.Files;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@@ -39,12 +39,16 @@ import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
-import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
class ActivityPage extends WizardPage implements SelectionListener {
private final NewProjectWizardState mValues;
private List mList;
private Button mCreateToggle;
+ private java.util.List<File> mTemplates;
private boolean mIgnore;
private boolean mShown;
@@ -64,11 +68,15 @@ class ActivityPage extends WizardPage implements SelectionListener {
setDescription("Select whether to create an activity, and if so, what kind of activity.");
}
- @SuppressWarnings("unused") // SWT constructors have side effects and aren't unused
@Override
public void createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NULL);
setControl(container);
+ }
+
+ @SuppressWarnings("unused") // SWT constructors have side effects and aren't unused
+ private void onEnter() {
+ Composite container = (Composite) getControl();
container.setLayout(new GridLayout(3, false));
mCreateToggle = new Button(container, SWT.CHECK);
@@ -79,20 +87,29 @@ class ActivityPage extends WizardPage implements SelectionListener {
mList = new List(container, SWT.BORDER | SWT.V_SCROLL);
mList.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
- mList.setItems(ACTIVITY_TEMPLATES);
+
+
+ mTemplates = TemplateHandler.getTemplates("activities");
+ java.util.List<String> names = new ArrayList<String>(mTemplates.size());
+ File current = mValues.activityValues.getTemplateLocation();
int index = -1;
- for (int i = 0; i < ACTIVITY_TEMPLATES.length; i++) {
- if (ACTIVITY_TEMPLATES[i].equals(mValues.activityValues.getTemplateName())) {
+ for (int i = 0, n = mTemplates.size(); i < n; i++) {
+ File template = mTemplates.get(i);
+ names.add(template.getName());
+ if (template.equals(current)) {
index = i;
- break;
}
}
- if (index == -1) {
- mValues.activityValues.setTemplateName(ACTIVITY_TEMPLATES[0]);
+ String[] items = names.toArray(new String[names.size()]);
+ mList.setItems(items);
+ if (index == -1 && !mTemplates.isEmpty()) {
+ mValues.activityValues.setTemplateLocation(mTemplates.get(0));
index = 0;
}
- mList.setSelection(index);
- mList.addSelectionListener(this);
+ if (index >= 0) {
+ mList.setSelection(index);
+ mList.addSelectionListener(this);
+ }
// Preview
mPreview = new ImageControl(container, SWT.NONE, null);
@@ -113,26 +130,29 @@ class ActivityPage extends WizardPage implements SelectionListener {
mHeading.setFont(font);
}
- setPreview(mValues.activityValues.getTemplateName());
+ updatePreview();
}
- private void setPreview(String templateName) {
+ private void updatePreview() {
Image oldImage = mPreviewImage;
mPreviewImage = null;
String title = "";
String description = "";
- TemplateMetadata template = TemplateHandler.getTemplate(templateName);
+ TemplateHandler handler = mValues.activityValues.getTemplateHandler();
+ TemplateMetadata template = handler.getTemplate();
if (template != null) {
String thumb = template.getThumbnailPath();
if (thumb != null && !thumb.isEmpty()) {
- String filePath = TemplateHandler.getTemplatePath(templateName) + '/' + thumb;
- InputStream input = AdtPlugin.readEmbeddedFileAsStream(filePath);
- if (input != null) {
+ File file = new File(mValues.activityValues.getTemplateLocation(),
+ thumb.replace('/', File.separatorChar));
+ if (file != null) {
try {
+ byte[] bytes = Files.toByteArray(file);
+ ByteArrayInputStream input = new ByteArrayInputStream(bytes);
mPreviewImage = new Image(getControl().getDisplay(), input);
input.close();
- } catch (Exception e) {
+ } catch (IOException e) {
AdtPlugin.log(e, null);
}
}
@@ -167,6 +187,10 @@ class ActivityPage extends WizardPage implements SelectionListener {
@Override
public void setVisible(boolean visible) {
+ if (visible && !mShown) {
+ onEnter();
+ }
+
super.setVisible(visible);
if (visible) {
@@ -233,11 +257,10 @@ class ActivityPage extends WizardPage implements SelectionListener {
mList.setEnabled(mValues.createActivity);
} else if (source == mList) {
int index = mList.getSelectionIndex();
- String[] items = mList.getItems();
- if (index >= 0 && index < items.length) {
- String templateName = items[index];
- mValues.activityValues.setTemplateName(templateName);
- setPreview(templateName);
+ if (index >= 0 && index < mTemplates.size()) {
+ File template = mTemplates.get(index);
+ mValues.activityValues.setTemplateLocation(template);
+ updatePreview();
}
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java
index a6f2a9e..fbd50e9 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmActivityToLayoutMethod.java
@@ -16,6 +16,7 @@
package com.android.ide.eclipse.adt.internal.wizards.templates;
import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectPage.ACTIVITY_NAME_SUFFIX;
+import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectPage.LAYOUT_NAME_PREFIX;
import com.android.ide.eclipse.adt.AdtUtils;
@@ -39,6 +40,10 @@ public class FmActivityToLayoutMethod implements TemplateMethodModel {
String activityName = args.get(0).toString();
+ if (activityName.isEmpty()) {
+ return new SimpleScalar("");
+ }
+
// Strip off the end portion of the activity name. The user might be typing
// the activity name such that only a portion has been entered so far (e.g.
// "MainActivi") and we want to chop off that portion too such that we don't
@@ -52,7 +57,7 @@ public class FmActivityToLayoutMethod implements TemplateMethodModel {
// Convert CamelCase convention used in activity class names to underlined convention
// used in layout name:
- String name = AdtUtils.camelCaseToUnderlines(activityName);
+ String name = LAYOUT_NAME_PREFIX + AdtUtils.camelCaseToUnderlines(activityName);
return new SimpleScalar(name);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java
index f3dd9cd..6514959 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/FmLayoutToActivityMethod.java
@@ -17,6 +17,7 @@ package com.android.ide.eclipse.adt.internal.wizards.templates;
import static com.android.ide.eclipse.adt.AdtUtils.extractClassName;
import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectPage.ACTIVITY_NAME_SUFFIX;
+import static com.android.ide.eclipse.adt.internal.wizards.templates.NewProjectPage.LAYOUT_NAME_PREFIX;
import com.android.ide.eclipse.adt.AdtUtils;
@@ -39,6 +40,15 @@ public class FmLayoutToActivityMethod implements TemplateMethodModel {
}
String name = args.get(0).toString();
+
+ // Strip off the beginning portion of the layout name. The user might be typing
+ // the activity name such that only a portion has been entered so far (e.g.
+ // "MainActivi") and we want to chop off that portion too such that we don't
+ // offer a layout name partially containing the activity suffix (e.g. "main_activi").
+ if (name.startsWith(LAYOUT_NAME_PREFIX)) {
+ name = name.substring(LAYOUT_NAME_PREFIX.length());
+ }
+
name = AdtUtils.underlinesToCamelCase(name);
String className = extractClassName(name);
if (className == null) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java
index 0c40fab..800366a 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectPage.java
@@ -68,7 +68,9 @@ public class NewProjectPage extends WizardPage
implements ModifyListener, SelectionListener, FocusListener {
private static final String SAMPLE_PACKAGE_PREFIX = "com.example."; //$NON-NLS-1$
/** Suffix added by default to activity names */
- static final String ACTIVITY_NAME_SUFFIX = "Activity"; //$NON-NLS-1$
+ static final String ACTIVITY_NAME_SUFFIX = "Activity"; //$NON-NLS-1$
+ /** Prefix added to default layout names */
+ static final String LAYOUT_NAME_PREFIX = "activity_"; //$NON-NLS-1$
private static final int INITIAL_MIN_SDK = 8;
private final NewProjectWizardState mValues;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java
index 60f7a9e..5e359a4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizard.java
@@ -41,6 +41,7 @@ import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
@@ -70,6 +71,7 @@ public class NewProjectWizard extends Wizard implements INewWizard {
private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
private IWorkbench mWorkbench;
+ private UpdateToolsPage mUpdatePage;
private NewProjectPage mMainPage;
private AppSkeletonPage mAppSkeletonPage;
private NewTemplatePage mTemplatePage;
@@ -85,6 +87,10 @@ public class NewProjectWizard extends Wizard implements INewWizard {
setHelpAvailable(false);
setImageDescriptor();
+ if (!UpdateToolsPage.isUpToDate()) {
+ mUpdatePage = new UpdateToolsPage();
+ }
+
mValues = new NewProjectWizardState();
mMainPage = new NewProjectPage(mValues);
mAppSkeletonPage = new AppSkeletonPage(mValues);
@@ -96,12 +102,24 @@ public class NewProjectWizard extends Wizard implements INewWizard {
*/
@Override
public void addPages() {
+ if (mUpdatePage != null) {
+ addPage(mUpdatePage);
+ }
+
addPage(mMainPage);
addPage(mAppSkeletonPage);
addPage(mActivityPage);
}
@Override
+ public IWizardPage getStartingPage() {
+ if (mUpdatePage != null && mUpdatePage.isPageComplete()) {
+ return mMainPage;
+ }
+ return super.getStartingPage();
+ }
+
+ @Override
public IWizardPage getNextPage(IWizardPage page) {
// If you turn off creating an application, only one page
if (page == mMainPage) {
@@ -197,6 +215,10 @@ public class NewProjectWizard extends Wizard implements INewWizard {
@Override
public boolean performFinish() {
try {
+ Shell shell = getShell();
+ if (shell != null) {
+ shell.setVisible(false);
+ }
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
String name = mValues.projectName;
final IProject newProject = root.getProject(name);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java
index 48a781f..1dc81ca 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewProjectWizardState.java
@@ -19,19 +19,16 @@ package com.android.ide.eclipse.adt.internal.wizards.templates;
import com.android.ide.eclipse.adt.internal.assetstudio.CreateAssetSetWizardState;
import com.android.sdklib.IAndroidTarget;
-import java.io.File;
-
/**
* Value object which holds the current state of the wizard pages for the
* {@link NewProjectWizard}
*/
public class NewProjectWizardState {
- private static final String TEMPLATE_NAME = "NewAndroidApplication"; //$NON-NLS-1$
+ private static final String TEMPLATE_NAME = "projects/NewAndroidApplication"; //$NON-NLS-1$
/** Creates a new {@link NewProjectWizardState} */
public NewProjectWizardState() {
- File inputPath = new File(TemplateHandler.getTemplatePath(TEMPLATE_NAME));
- template = TemplateHandler.createFromPath(inputPath);
+ template = TemplateHandler.createFromName(TEMPLATE_NAME);
}
/** The template handler instantiating the project */
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
index a6fdf48..eece39b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplatePage.java
@@ -20,21 +20,41 @@ import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHan
import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.ATTR_NAME;
import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_PADDING;
import static com.android.ide.eclipse.adt.internal.wizards.templates.TemplateHandler.PREVIEW_WIDTH;
+import static com.android.sdklib.SdkConstants.CLASS_ACTIVITY;
import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.IconFactory;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.ImageControl;
+import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper;
import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper;
import com.android.ide.eclipse.adt.internal.project.ProjectChooserHelper.ProjectCombo;
+import com.android.ide.eclipse.adt.internal.wizards.templates.Parameter.Type;
import com.android.tools.lint.detector.api.LintUtils;
import com.google.common.collect.Lists;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeHierarchy;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.search.IJavaSearchScope;
+import org.eclipse.jdt.core.search.SearchEngine;
+import org.eclipse.jdt.ui.IJavaElementSearchConstants;
+import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jdt.ui.dialogs.ITypeInfoFilterExtension;
+import org.eclipse.jdt.ui.dialogs.ITypeInfoRequestor;
+import org.eclipse.jdt.ui.dialogs.TypeSelectionExtension;
+import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.IMessageProvider;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
@@ -54,7 +74,9 @@ import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.SelectionDialog;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
@@ -162,11 +184,11 @@ public class NewTemplatePage extends WizardPage
if (template != null) {
thumb = template.getThumbnailPath();
String title = template.getTitle();
- if (!title.isEmpty()) {
+ if (title != null && !title.isEmpty()) {
setTitle(title);
}
String description = template.getDescription();
- if (!description.isEmpty()) {
+ if (description != null && !description.isEmpty()) {
setDescription(description);
}
@@ -210,116 +232,144 @@ public class NewTemplatePage extends WizardPage
continue;
}
- if (type == Parameter.Type.STRING) {
- // TODO: Look at the constraints to add validators here
- // TODO: If I type.equals("layout") add resource validator for layout
- // names
- // TODO: If I type.equals("class") make class validator
-
- // TODO: Handle package and id better later
- Label label = new Label(container, SWT.NONE);
- label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- label.setText(name);
-
- Text text = new Text(container, SWT.BORDER);
- text.setData(parameter);
- parameter.control = text;
- text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
-
- if (value != null && !value.isEmpty()){
- text.setText(value);
- mValues.parameters.put(id, value);
- }
+ switch (type) {
+ case STRING: {
+ // TODO: Look at the constraints to add validators here
+ // TODO: If I type.equals("layout") add resource validator for layout
+ // names
+ // TODO: If I type.equals("class") make class validator
+
+ // TODO: Handle package and id better later
+ Label label = new Label(container, SWT.NONE);
+ label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false,
+ 1, 1));
+ label.setText(name);
+
+ Text text = new Text(container, SWT.BORDER);
+ text.setData(parameter);
+ parameter.control = text;
+
+ if (parameter.constraints.contains(Parameter.Constraint.EXISTS)) {
+ text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
+ 1, 1));
+
+ Button button = new Button(container, SWT.FLAT);
+ button.setData(parameter);
+ button.setText("...");
+ button.addSelectionListener(this);
+ } else {
+ text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
+ 2, 1));
+ }
- text.addModifyListener(this);
- text.addFocusListener(this);
+ if (value != null && !value.isEmpty()){
+ text.setText(value);
+ mValues.parameters.put(id, value);
+ }
- if (mFirst == null) {
- mFirst = text;
- }
+ text.addModifyListener(this);
+ text.addFocusListener(this);
- if (help != null && !help.isEmpty()) {
- text.setToolTipText(help);
- ControlDecoration decoration = createFieldDecoration(id, text, help);
- }
- } else if (type == Parameter.Type.BOOLEAN) {
- Label label = new Label(container, SWT.NONE);
- label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
-
- Button checkBox = new Button(container, SWT.CHECK);
- checkBox.setText(name);
- checkBox.setData(parameter);
- parameter.control = checkBox;
- checkBox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
-
- if (value != null && !value.isEmpty()){
- Boolean selected = Boolean.valueOf(value);
- checkBox.setSelection(selected);
- mValues.parameters.put(id, value);
- }
-
- checkBox.addSelectionListener(this);
- checkBox.addFocusListener(this);
+ if (mFirst == null) {
+ mFirst = text;
+ }
- if (mFirst == null) {
- mFirst = checkBox;
+ if (help != null && !help.isEmpty()) {
+ text.setToolTipText(help);
+ ControlDecoration decoration = createFieldDecoration(id, text, help);
+ }
+ break;
}
+ case BOOLEAN: {
+ Label label = new Label(container, SWT.NONE);
+ label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false,
+ 1, 1));
+
+ Button checkBox = new Button(container, SWT.CHECK);
+ checkBox.setText(name);
+ checkBox.setData(parameter);
+ parameter.control = checkBox;
+ checkBox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
+ 2, 1));
+
+ if (value != null && !value.isEmpty()){
+ Boolean selected = Boolean.valueOf(value);
+ checkBox.setSelection(selected);
+ mValues.parameters.put(id, value);
+ }
- if (help != null && !help.isEmpty()) {
- checkBox.setToolTipText(help);
- ControlDecoration decoration = createFieldDecoration(id, checkBox, help);
- }
+ checkBox.addSelectionListener(this);
+ checkBox.addFocusListener(this);
- } else if (type == Parameter.Type.ENUM) {
- Label label = new Label(container, SWT.NONE);
- label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
- label.setText(name);
-
- Combo combo = new Combo(container, SWT.READ_ONLY);
- combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
-
- List<Element> options = DomUtilities.getChildren(parameter.element);
- assert options.size() > 0;
- int selected = 0;
- List<String> ids = Lists.newArrayList();
- List<String> labels = Lists.newArrayList();
- for (int i = 0, n = options.size(); i < n; i++) {
- Element option = options.get(i);
- String optionId = option.getAttribute(ATTR_ID);
- assert optionId != null && !optionId.isEmpty() : ATTR_ID;
- String isDefault = option.getAttribute(ATTR_DEFAULT);
- if (isDefault != null && !isDefault.isEmpty() &&
- Boolean.valueOf(isDefault)) {
- selected = i;
+ if (mFirst == null) {
+ mFirst = checkBox;
}
- NodeList childNodes = option.getChildNodes();
- assert childNodes.getLength() == 1 &&
- childNodes.item(0).getNodeType() == Node.TEXT_NODE;
- String optionLabel = childNodes.item(0).getNodeValue().trim();
- ids.add(optionId);
- labels.add(optionLabel);
- }
- combo.setData(parameter);
- parameter.control = combo;
- combo.setData(ATTR_ID, ids.toArray(new String[ids.size()]));
- assert labels.size() > 0;
- combo.setItems(labels.toArray(new String[labels.size()]));
- combo.select(selected);
- mValues.parameters.put(id, ids.get(selected));
-
- combo.addSelectionListener(this);
- combo.addFocusListener(this);
-
- if (mFirst == null) {
- mFirst = combo;
+
+ if (help != null && !help.isEmpty()) {
+ checkBox.setToolTipText(help);
+ ControlDecoration decoration = createFieldDecoration(id, checkBox,
+ help);
+ }
+ break;
}
+ case ENUM: {
+ Label label = new Label(container, SWT.NONE);
+ label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false,
+ 1, 1));
+ label.setText(name);
+
+ Combo combo = new Combo(container, SWT.READ_ONLY);
+ combo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false,
+ 2, 1));
+
+ List<Element> options = DomUtilities.getChildren(parameter.element);
+ assert options.size() > 0;
+ int selected = 0;
+ List<String> ids = Lists.newArrayList();
+ List<String> labels = Lists.newArrayList();
+ for (int i = 0, n = options.size(); i < n; i++) {
+ Element option = options.get(i);
+ String optionId = option.getAttribute(ATTR_ID);
+ assert optionId != null && !optionId.isEmpty() : ATTR_ID;
+ String isDefault = option.getAttribute(ATTR_DEFAULT);
+ if (isDefault != null && !isDefault.isEmpty() &&
+ Boolean.valueOf(isDefault)) {
+ selected = i;
+ }
+ NodeList childNodes = option.getChildNodes();
+ assert childNodes.getLength() == 1 &&
+ childNodes.item(0).getNodeType() == Node.TEXT_NODE;
+ String optionLabel = childNodes.item(0).getNodeValue().trim();
+ ids.add(optionId);
+ labels.add(optionLabel);
+ }
+ combo.setData(parameter);
+ parameter.control = combo;
+ combo.setData(ATTR_ID, ids.toArray(new String[ids.size()]));
+ assert labels.size() > 0;
+ combo.setItems(labels.toArray(new String[labels.size()]));
+ combo.select(selected);
+ mValues.parameters.put(id, ids.get(selected));
+
+ combo.addSelectionListener(this);
+ combo.addFocusListener(this);
+
+ if (mFirst == null) {
+ mFirst = combo;
+ }
- if (help != null && !help.isEmpty()) {
- combo.setToolTipText(help);
- ControlDecoration decoration = createFieldDecoration(id, combo, help);
+ if (help != null && !help.isEmpty()) {
+ combo.setToolTipText(help);
+ ControlDecoration decoration = createFieldDecoration(id, combo, help);
+ }
+ break;
}
- } else {
- assert false : type;
+ case SEPARATOR:
+ // Already handled above
+ assert false : type;
+ break;
+ default:
+ assert false : type;
}
}
}
@@ -539,19 +589,105 @@ public class NewTemplatePage extends WizardPage
String optionId = optionIds[index];
editParameter(combo, optionId);
TemplateMetadata template = mValues.getTemplateHandler().getTemplate();
- setPreview(template.getThumbnailPath());
+ if (template != null) {
+ setPreview(template.getThumbnailPath());
+ }
}
} else if (source instanceof Button) {
Button button = (Button) source;
- editParameter(button, button.getSelection());
+ Parameter parameter = (Parameter) button.getData();
+ if (parameter.type == Type.BOOLEAN) {
+ // Checkbox parameter
+ editParameter(button, button.getSelection());
- TemplateMetadata template = mValues.getTemplateHandler().getTemplate();
- setPreview(template.getThumbnailPath());
+ TemplateMetadata template = mValues.getTemplateHandler().getTemplate();
+ if (template != null) {
+ setPreview(template.getThumbnailPath());
+ }
+ } else {
+ // Choose button for some other parameter, usually a text
+ String activity = chooseActivity();
+ if (activity != null) {
+ setValue(parameter, activity);
+ }
+ }
}
validatePage();
}
+ private String chooseActivity() {
+ try {
+ // Compute a search scope: We need to merge all the subclasses
+ // android.app.Fragment and android.support.v4.app.Fragment
+ IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
+ IProject project = mValues.project;
+ IJavaProject javaProject = BaseProjectHelper.getJavaProject(project);
+ IType activityType = null;
+
+ if (javaProject != null) {
+ activityType = javaProject.findType(CLASS_ACTIVITY);
+ }
+ if (activityType == null) {
+ IJavaProject[] projects = BaseProjectHelper.getAndroidProjects(null);
+ for (IJavaProject p : projects) {
+ activityType = p.findType(CLASS_ACTIVITY);
+ if (activityType != null) {
+ break;
+ }
+ }
+ }
+ if (activityType != null) {
+ NullProgressMonitor monitor = new NullProgressMonitor();
+ ITypeHierarchy hierarchy = activityType.newTypeHierarchy(monitor);
+ IType[] classes = hierarchy.getAllSubtypes(activityType);
+ scope = SearchEngine.createJavaSearchScope(classes, IJavaSearchScope.SOURCES);
+ }
+
+ Shell parent = AdtPlugin.getDisplay().getActiveShell();
+ final SelectionDialog dialog = JavaUI.createTypeDialog(
+ parent,
+ new ProgressMonitorDialog(parent),
+ scope,
+ IJavaElementSearchConstants.CONSIDER_CLASSES, false,
+ // Use ? as a default filter to fill dialog with matches
+ "?", //$NON-NLS-1$
+ new TypeSelectionExtension() {
+ @Override
+ public ITypeInfoFilterExtension getFilterExtension() {
+ return new ITypeInfoFilterExtension() {
+ @Override
+ public boolean select(ITypeInfoRequestor typeInfoRequestor) {
+ int modifiers = typeInfoRequestor.getModifiers();
+ if (!Flags.isPublic(modifiers)
+ || Flags.isInterface(modifiers)
+ || Flags.isEnum(modifiers)) {
+ return false;
+ }
+ return true;
+ }
+ };
+ }
+ });
+
+ dialog.setTitle("Choose Activity Class");
+ dialog.setMessage("Select an Activity class (? = any character, * = any string):");
+ if (dialog.open() == IDialogConstants.CANCEL_ID) {
+ return null;
+ }
+
+ Object[] types = dialog.getResult();
+ if (types != null && types.length > 0) {
+ return ((IType) types[0]).getFullyQualifiedName();
+ }
+ } catch (JavaModelException e) {
+ AdtPlugin.log(e, null);
+ } catch (CoreException e) {
+ AdtPlugin.log(e, null);
+ }
+ return null;
+ }
+
private void editParameter(Control control, Object value) {
Parameter parameter = getParameter(control);
if (parameter != null) {
@@ -576,25 +712,7 @@ public class NewTemplatePage extends WizardPage
}
String updated = mEvaluator.evaluate(p.suggest, mParameters);
if (updated != null && !updated.equals(p.value)) {
- p.value = updated;
- mValues.parameters.put(p.id, updated);
-
- // Update form widgets
- boolean prevIgnore = mIgnore;
- try {
- mIgnore = true;
- if (p.control instanceof Text) {
- ((Text) p.control).setText(updated);
- } else if (p.control instanceof Button) {
- // TODO: Handle
- } else if (p.control instanceof Combo) {
- // TODO: Handle
- } else if (p.control != null) {
- assert false : p.control;
- }
- } finally {
- mIgnore = prevIgnore;
- }
+ setValue(p, updated);
}
} catch (Throwable t) {
// Pass: Ignore updating if something wrong happens
@@ -604,6 +722,28 @@ public class NewTemplatePage extends WizardPage
}
}
+ private void setValue(Parameter p, String value) {
+ p.value = value;
+ mValues.parameters.put(p.id, value);
+
+ // Update form widgets
+ boolean prevIgnore = mIgnore;
+ try {
+ mIgnore = true;
+ if (p.control instanceof Text) {
+ ((Text) p.control).setText(value);
+ } else if (p.control instanceof Button) {
+ // TODO: Handle
+ } else if (p.control instanceof Combo) {
+ // TODO: Handle
+ } else if (p.control != null) {
+ assert false : p.control;
+ }
+ } finally {
+ mIgnore = prevIgnore;
+ }
+ }
+
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java
index b7ad998..143db78 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizard.java
@@ -34,6 +34,7 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
@@ -50,18 +51,16 @@ import java.util.Set;
*/
public class NewTemplateWizard extends Wizard implements INewWizard {
/** Template name and location under /templates in the plugin */
- static final String BLANK_ACTIVITY = "BlankActivity"; //$NON-NLS-1$
+ static final String BLANK_ACTIVITY = "activities/BlankActivity"; //$NON-NLS-1$
/** Template name and location under /templates in the plugin */
- static final String MASTER_DETAIL_FLOW = "MasterDetailFlow"; //$NON-NLS-1$
+ static final String MASTER_DETAIL_FLOW = "activities/MasterDetailFlow"; //$NON-NLS-1$
/** Template name and location under /templates in the plugin */
- static final String CUSTOM_VIEW = "CustomView"; //$NON-NLS-1$
- /** Available activity-templates (included in a list in the new project template) */
- static final String[] ACTIVITY_TEMPLATES =
- new String[] { BLANK_ACTIVITY, MASTER_DETAIL_FLOW };
- private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
+ static final String CUSTOM_VIEW = "other/CustomView"; //$NON-NLS-1$
+ private static final String PROJECT_LOGO_LARGE = "android-64"; //$NON-NLS-1$
protected IWorkbench mWorkbench;
protected NewTemplatePage mMainPage;
+ protected UpdateToolsPage mUpdatePage;
protected NewTemplateWizardState mValues;
private final String mTemplateName;
@@ -77,9 +76,15 @@ public class NewTemplateWizard extends Wizard implements INewWizard {
setImageDescriptor();
mValues = new NewTemplateWizardState();
- mValues.setTemplateName(mTemplateName);
+
+ File template = TemplateHandler.getTemplateLocation(mTemplateName);
+ mValues.setTemplateLocation(template);
hideBuiltinParameters();
+ if (!UpdateToolsPage.isUpToDate()) {
+ mUpdatePage = new UpdateToolsPage();
+ }
+
List<IProject> projects = AdtUtils.getSelectedProjects(selection);
if (projects.size() == 1) {
mValues.project = projects.get(0);
@@ -103,10 +108,27 @@ public class NewTemplateWizard extends Wizard implements INewWizard {
@Override
public void addPages() {
+ if (mUpdatePage != null) {
+ addPage(mUpdatePage);
+ }
+
addPage(mMainPage);
}
@Override
+ public IWizardPage getNextPage(IWizardPage page) {
+ return super.getNextPage(page);
+ }
+
+ @Override
+ public IWizardPage getStartingPage() {
+ if (mUpdatePage != null && mUpdatePage.isPageComplete()) {
+ return mMainPage;
+ }
+ return super.getStartingPage();
+ }
+
+ @Override
public boolean performFinish() {
try {
Map<String, Object> parameters = mValues.parameters;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
index dc75a71..1fb73d8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/NewTemplateWizardState.java
@@ -33,9 +33,6 @@ import java.util.Set;
* {@link NewTemplateWizard}
*/
public class NewTemplateWizardState {
- /** Name of the template being created */
- private String mTemplateName = BLANK_ACTIVITY;
-
/** Template handler responsible for instantiating templates and reading resources */
private TemplateHandler mTemplateHandler;
@@ -55,7 +52,7 @@ public class NewTemplateWizardState {
*/
public IProject project;
- /** Name of the template being created */
+ /** Location of the template being created */
private File mTemplateLocation;
/**
@@ -65,31 +62,14 @@ public class NewTemplateWizardState {
}
@NonNull
- String getTemplateName() {
- return mTemplateName;
- }
-
- /**
- * Sets the new template name to use
- *
- * @param templateName the name of the template to use
- */
- void setTemplateName(@NonNull String templateName) {
- if (!templateName.equals(mTemplateName)) {
- mTemplateName = templateName;
- mTemplateLocation = null;
- mTemplateHandler = null;
- }
- }
-
- @NonNull
TemplateHandler getTemplateHandler() {
if (mTemplateHandler == null) {
File inputPath;
if (mTemplateLocation != null) {
inputPath = mTemplateLocation;
} else {
- inputPath = new File(TemplateHandler.getTemplatePath(mTemplateName));
+ // Default
+ inputPath = TemplateHandler.getTemplateLocation(BLANK_ACTIVITY);
}
mTemplateHandler = TemplateHandler.createFromPath(inputPath);
}
@@ -97,12 +77,18 @@ public class NewTemplateWizardState {
return mTemplateHandler;
}
- // For template development/testing only
+ /** Sets the current template */
void setTemplateLocation(File file) {
if (!file.equals(mTemplateLocation)) {
mTemplateLocation = file;
- mTemplateName = null;
mTemplateHandler = null;
}
}
+
+ /** Returns the current template */
+ File getTemplateLocation() {
+ return mTemplateLocation;
+ }
+
+
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java
index 0b8b952..7436a26 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/Parameter.java
@@ -97,6 +97,9 @@ class Parameter {
/** The associated value must not be empty */
NONEMPTY,
+ /** The associated value should represent a fully qualified activity class name */
+ ACTIVITY,
+
/** The associated value should represent an API level */
APILEVEL,
@@ -275,10 +278,19 @@ class Parameter {
mValidator = ResourceNameValidator.create(false, ResourceFolderType.DRAWABLE);
}
return mValidator;
- } else if (constraints.contains(Constraint.CLASS)) {
+ } else if (constraints.contains(Constraint.CLASS)
+ || constraints.contains(Constraint.ACTIVITY)) {
mValidator = new IInputValidator() {
@Override
public String isValid(String newText) {
+ // Deliberately allow empty strings for parameters that aren't required
+ if (newText.trim().isEmpty()
+ && !constraints.contains(Constraint.NONEMPTY)) {
+ return null;
+ }
+
+ // TODO: Don't use *activity* validator if it doesn't have to be one
+ // (e.g. is CLASS, not ACTIVITY)
IStatus status = ApplicationInfoPage.validateActivity(newText.trim());
if (status != null && !status.isOK()) {
return status.getMessage();
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
index 4f107fb..760084d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/TemplateHandler.java
@@ -16,8 +16,9 @@
package com.android.ide.eclipse.adt.internal.wizards.templates;
import static com.android.ide.eclipse.adt.AdtConstants.DOT_FTL;
-import static com.android.ide.eclipse.adt.AdtConstants.DOT_JAR;
import static com.android.ide.eclipse.adt.AdtConstants.DOT_XML;
+import static com.android.sdklib.SdkConstants.FD_TEMPLATES;
+import static com.android.sdklib.SdkConstants.FD_TOOLS;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
@@ -27,11 +28,11 @@ import com.android.ide.eclipse.adt.internal.editors.formatting.XmlFormatPreferen
import com.android.ide.eclipse.adt.internal.editors.formatting.XmlFormatStyle;
import com.android.ide.eclipse.adt.internal.editors.formatting.XmlPrettyPrinter;
import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities;
+import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.manifmerger.ManifestMerger;
import com.android.resources.ResourceFolderType;
import com.android.sdklib.SdkConstants;
import com.google.common.base.Charsets;
-import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
import freemarker.cache.TemplateLoader;
@@ -54,22 +55,16 @@ import org.xml.sax.helpers.DefaultHandler;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
-import java.net.URI;
import java.net.URL;
-import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
@@ -98,10 +93,7 @@ class TemplateHandler {
* Shared resource directory containing common resources shared among
* multiple templates
*/
- private static final String RESOURCE_ROOT = "res"; //$NON-NLS-1$
-
- /** Relative path within the ADT plugin where the templates are found */
- static final String TEMPLATE_PREFIX = "/templates/"; //$NON-NLS-1$
+ private static final String RESOURCE_ROOT = "resources"; //$NON-NLS-1$
/** Reserved filename which describes each template */
static final String TEMPLATE_XML = "template.xml"; //$NON-NLS-1$
@@ -132,6 +124,11 @@ class TemplateHandler {
static final String ATTR_FROM = "from"; //$NON-NLS-1$
static final String ATTR_CONSTRAINTS = "constraints";//$NON-NLS-1$
+ static final String CATEGORY_ACTIVITIES = "activities";//$NON-NLS-1$
+ static final String CATEGORY_PROJECTS = "projects"; //$NON-NLS-1$
+ static final String CATEGORY_OTHER = "other"; //$NON-NLS-1$
+
+
/** Default padding to apply in wizards around the thumbnail preview images */
static final int PREVIEW_PADDING = 10;
@@ -145,6 +142,7 @@ class TemplateHandler {
private final List<String> mOpen = Lists.newArrayList();
/** Path to the directory containing the templates */
+ @NonNull
private final File mRootPath;
/** The template loader which is responsible for finding (and sharing) template files */
@@ -172,6 +170,12 @@ class TemplateHandler {
return new TemplateHandler(rootPath);
}
+ /** Creates a new {@link TemplateHandler} for the template name, which should
+ * be relative to the templates directory */
+ static TemplateHandler createFromName(String relative) {
+ return new TemplateHandler(new File(getTemplateRootFolder(), relative));
+ }
+
private TemplateHandler(File rootPath) {
mRootPath = rootPath;
mLoader = new MyTemplateLoader();
@@ -244,26 +248,75 @@ class TemplateHandler {
@Nullable
public static TemplateMetadata getTemplate(String templateName) {
- String relative = getTemplatePath(templateName) + '/' +TEMPLATE_XML;
- String xml = AdtPlugin.readEmbeddedTextFile(relative);
- Document doc = DomUtilities.parseDocument(xml, true);
- if (doc != null && doc.getDocumentElement() != null) {
- return new TemplateMetadata(doc);
+ String relative = templateName + '/' + TEMPLATE_XML;
+
+ File templateFile = getTemplateLocation(relative);
+ if (templateFile != null) {
+ try {
+ String xml = Files.toString(templateFile, Charsets.UTF_8);
+ Document doc = DomUtilities.parseDocument(xml, true);
+ if (doc != null && doc.getDocumentElement() != null) {
+ return new TemplateMetadata(doc);
+ }
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ return null;
+ }
}
return null;
}
@NonNull
- public static String getTemplatePath(String templateName) {
- return TEMPLATE_PREFIX + templateName;
- }
-
- @NonNull
public String getResourcePath(String templateName) {
return new File(mRootPath.getPath(), templateName).getPath();
}
+ @Nullable
+ public static File getTemplateRootFolder() {
+ String location = AdtPrefs.getPrefs().getOsSdkFolder();
+ if (location != null) {
+ File folder = new File(location, FD_TOOLS + File.separator + FD_TEMPLATES);
+ if (folder.isDirectory()) {
+ return folder;
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ public static File getTemplateLocation(@NonNull File root, @NonNull String relativePath) {
+ File templateRoot = getTemplateRootFolder();
+ if (templateRoot != null) {
+ String rootPath = root.getPath();
+ File templateFile = new File(templateRoot,
+ rootPath.replace('/', File.separatorChar) + File.separator
+ + relativePath.replace('/', File.separatorChar));
+ if (templateFile.exists()) {
+ return templateFile;
+ }
+ }
+
+ return null;
+
+ }
+
+ @Nullable
+ public static File getTemplateLocation(@NonNull String relativePath) {
+ File templateRoot = getTemplateRootFolder();
+ if (templateRoot != null) {
+ File templateFile = new File(templateRoot,
+ relativePath.replace('/', File.separatorChar));
+ if (templateFile.exists()) {
+ return templateFile;
+ }
+ }
+
+ return null;
+
+ }
+
/**
* Load a text resource for the given relative path within the template
*
@@ -272,29 +325,23 @@ class TemplateHandler {
*/
@Nullable
public String readTemplateTextResource(@NonNull String relativePath) {
- if (mRootPath.getPath().startsWith(TEMPLATE_PREFIX)) {
- return AdtPlugin.readEmbeddedTextFile(getResourcePath(relativePath));
- } else {
- try {
- return Files.toString(new File(mRootPath, relativePath), Charsets.UTF_8);
- } catch (IOException e) {
- AdtPlugin.log(e, null);
- return null;
- }
+ try {
+ return Files.toString(new File(mRootPath,
+ relativePath.replace('/', File.separatorChar)), Charsets.UTF_8);
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ return null;
}
}
@Nullable
public String readTemplateTextResource(@NonNull File file) {
- if (mRootPath.getPath().startsWith(TEMPLATE_PREFIX)) {
- return AdtPlugin.readEmbeddedTextFile(file.getPath());
- } else {
- try {
- return Files.toString(file, Charsets.UTF_8);
- } catch (IOException e) {
- AdtPlugin.log(e, null);
- return null;
- }
+ assert file.isAbsolute();
+ try {
+ return Files.toString(file, Charsets.UTF_8);
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ return null;
}
}
@@ -306,15 +353,11 @@ class TemplateHandler {
*/
@Nullable
public byte[] readTemplateResource(@NonNull String relativePath) {
- if (mRootPath.getPath().startsWith(TEMPLATE_PREFIX)) {
- return AdtPlugin.readEmbeddedFile(getResourcePath(relativePath));
- } else {
- try {
- return Files.toByteArray(new File(mRootPath, relativePath));
- } catch (IOException e) {
- AdtPlugin.log(e, null);
- return null;
- }
+ try {
+ return Files.toByteArray(new File(mRootPath, relativePath));
+ } catch (IOException e) {
+ AdtPlugin.log(e, null);
+ return null;
}
}
@@ -326,6 +369,9 @@ class TemplateHandler {
if (file.endsWith(DOT_XML)) {
// Just read the file
xml = readTemplateTextResource(file);
+ if (xml == null) {
+ return;
+ }
} else {
mLoader.setTemplateFile(new File(mRootPath, file));
Template inputsTemplate = freemarker.getTemplate(file);
@@ -366,7 +412,8 @@ class TemplateHandler {
execute(freemarker, path, paramMap, outputPath);
}
} else if (!name.equals("template") && !name.equals("category")
- && !name.equals("option")) {
+ && !name.equals("option") && !name.equals(TAG_THUMBS) &&
+ !name.equals(TAG_THUMB)) {
System.err.println("WARNING: Unknown template directive " + name);
}
}
@@ -492,10 +539,12 @@ class TemplateHandler {
}
}
- private File getFullPath(String fromPath) {
+ @NonNull
+ private File getFullPath(@NonNull String fromPath) {
if (fromPath.startsWith(VALUE_TEMPLATE_DIR)) {
- return new File(mRootPath.getParentFile(), RESOURCE_ROOT
- + fromPath.substring(VALUE_TEMPLATE_DIR.length()));
+ return new File(getTemplateRootFolder(), RESOURCE_ROOT + File.separator
+ + fromPath.substring(VALUE_TEMPLATE_DIR.length() + 1).replace('/',
+ File.separatorChar));
}
return new File(mRootPath, DATA_ROOT + File.separator + fromPath);
}
@@ -616,37 +665,6 @@ class TemplateHandler {
}
}
- /**
- * Writes the given contents into the given file (unless that file already
- * contains the given contents), and if the file exists ask user whether
- * the file should be overwritten (unless the user has already answered "Yes to All"
- * or "Cancel" (no to all).
- */
- private void writeBytes(File destination, byte[] contents, boolean confirmOverwrite)
- throws IOException {
- // First make sure that the files aren't identical, in which case we can do
- // nothing (and not involve user)
- if (!(destination.exists() && isIdentical(contents, destination))) {
- // And if the file does exist (and is now known to be different),
- // ask user whether it should be replaced (canOverwrite will also
- // return true if the file doesn't exist)
- if (confirmOverwrite) {
- if (!canOverwrite(destination)) {
- return;
- }
- } else {
- if (destination.exists()) {
- if (mBackupMergedFiles) {
- makeBackup(destination);
- } else {
- destination.delete();
- }
- }
- }
- Files.write(contents, destination);
- }
- }
-
/** Merges the given resource file contents into the given resource file
* @param paramMap */
private boolean mergeResourceFile(Document currentManifest, Document fragment,
@@ -810,60 +828,11 @@ class TemplateHandler {
}
/** Copy a bundled resource (part of the plugin .jar file) into the given file system path */
- private final void copyBundledResource(String relativeFrom, File output) throws IOException {
+ private final void copyBundledResource(
+ @NonNull String relativeFrom,
+ @NonNull File output) throws IOException {
File from = getFullPath(relativeFrom);
-
- // Local file copy? (Only used for the template-development wizard)
- if (!mRootPath.getPath().startsWith(TEMPLATE_PREFIX)) {
- copy(from, output);
- return;
- }
-
- String resourcePath = from.getPath();
- CodeSource source = TemplateHandler.class.getProtectionDomain().getCodeSource();
- if (source != null) {
- URL location = source.getLocation();
- try {
- URI locationUri = location.toURI();
- File locationFile = new File(locationUri);
- if (!locationUri.getPath().endsWith(DOT_JAR)) {
- // Plain file; e.g. when running out of Eclipse plugin in
- // Eclipse; it uses the bin/ folder instead of running out of a jar
- File sourceFile = new File(locationFile, resourcePath);
- copy(sourceFile, output);
- return;
- }
-
- // Copy out of jar file
- JarFile jarFile = new JarFile(locationFile);
- int chopIndex = resourcePath.length() + 1;
- for (final Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements();) {
- final JarEntry entry = e.nextElement();
- if (entry.getName().startsWith(resourcePath)) {
- final String filename = entry.getName().substring(chopIndex);
- assert entry.getName().charAt(resourcePath.length()) == '/';
- final File file = new File(output, filename);
- if (!entry.isDirectory()) {
- // Copy stream
- InputStream in = jarFile.getInputStream(entry);
- try {
- byte[] data = ByteStreams.toByteArray(in);
- writeBytes(output, data, true);
- } finally {
- in.close();
- }
- } else {
- // Create directory
- if (!file.exists() && !file.mkdirs()) {
- throw new IOException("Could not create directory " + file);
- }
- }
- }
- }
- } catch (Exception e) {
- AdtPlugin.log(e, null);
- }
- }
+ copy(from, output);
}
/** Returns true if the given file contains the given bytes */
@@ -939,21 +908,36 @@ class TemplateHandler {
@Override
public Object findTemplateSource(String name) throws IOException {
String path = mPrefix != null ? mPrefix + '/' + name : name;
- URL resource = TemplateHandler.class.getResource(path);
-
- // Support for local files during template development
- if (resource == null && mPrefix != null && !mPrefix.startsWith(TEMPLATE_PREFIX)) {
- File file = new File(path);
- if (file.exists()) {
- return file.toURI().toURL();
- }
+ File file = new File(path);
+ if (file.exists()) {
+ return file.toURI().toURL();
}
-
- return resource;
+ return null;
}
@Override
public void closeTemplateSource(Object templateSource) throws IOException {
}
}
+
+ /** Returns all the templates with the given prefix
+ *
+ * @param folder the folder prefix
+ * @return the available templates
+ */
+ @NonNull
+ static List<File> getTemplates(@NonNull String folder) {
+ List<File> templates = new ArrayList<File>();
+ File root = getTemplateRootFolder();
+ if (root != null) {
+ File[] files = new File(root, folder).listFiles();
+ if (files != null) {
+ for (File file : files) {
+ templates.add(file);
+ }
+ }
+ }
+
+ return templates;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/UpdateToolsPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/UpdateToolsPage.java
new file mode 100644
index 0000000..72713b2
--- /dev/null
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/templates/UpdateToolsPage.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 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.wizards.templates;
+
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+class UpdateToolsPage extends WizardPage implements SelectionListener {
+ private Button mInstallButton;
+ UpdateToolsPage() {
+ super("update");
+ setTitle("Update Tools");
+ validatePage();
+ }
+
+ @Override
+ public void createControl(Composite parent) {
+ Composite container = new Composite(parent, SWT.NULL);
+ setControl(container);
+ container.setLayout(new GridLayout(1, false));
+
+ Label label = new Label(container, SWT.WRAP);
+ GridData layoutData = new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1);
+ layoutData.widthHint = NewTemplatePage.WIZARD_PAGE_WIDTH - 50;
+ label.setLayoutData(layoutData);
+ label.setText(
+ "Your tools installation appears to be out of date (or not yet installed).\n" +
+ "\n" +
+ "This wizard depends on templates distributed with the Android SDK Tools.\n" +
+ "\n" +
+ "Please update the tools first (via Window > Android SDK Manager, or by " +
+ "using the \"android\" command in a terminal window). Note that on Windows " +
+ "you may need to restart the IDE, since there are some known problems where " +
+ "Windows locks the files held open by the running IDE, so the updater is " +
+ "unable to delete them in order to upgrade them.");
+
+ mInstallButton = new Button(container, SWT.NONE);
+ mInstallButton.setText("Check Again");
+ mInstallButton.addSelectionListener(this);
+ }
+
+ @Override
+ public boolean isPageComplete() {
+ return isUpToDate();
+ }
+
+ static boolean isUpToDate() {
+ return TemplateHandler.getTemplateRootFolder() != null;
+ }
+
+ private void validatePage() {
+ boolean ok = isUpToDate();
+ setPageComplete(ok);
+ if (ok) {
+ setErrorMessage(null);
+ setMessage(null);
+ } else {
+ setErrorMessage("The tools need to be updated via the SDK Manager");
+ }
+ }
+
+ // ---- Implements SelectionListener ----
+
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ if (e.getSource() == mInstallButton) {
+ validatePage();
+ }
+ }
+
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ }
+}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/messages.properties b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/messages.properties
index 1478f97..b37b809 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/messages.properties
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/messages.properties
@@ -1,7 +1,7 @@
Could_Not_Find_Folder=Could not find SDK folder '%1$s'.
Could_Not_Find_Folder_In_SDK=Could not find folder '%1$s' inside SDK '%2$s'.
Could_Not_Find=Could not find %1$s\!
-VersionCheck_Tools_Too_Old=This version of ADT requires Android SDK Tools in revision %1$d or above.\n\nCurrent revision is %2$d.\n\nPlease update your SDK Tools to the latest version.
+VersionCheck_Tools_Too_Old=This version of ADT requires Android SDK Tools in revision %1$s or above.\n\nCurrent revision is %2$s.\n\nPlease update your SDK Tools to the latest version.
VersionCheck_Plugin_Version_Failed=Failed to get the required ADT version number from the SDK.\n\nThe Android Developer Toolkit may not work properly.
VersionCheck_Unable_To_Parse_Version_s=Unable to parse sdk build version: %1$s
VersionCheck_Plugin_Too_Old=This Android SDK requires Android Developer Toolkit version %1$d.%2$d.%3$d or above.\n\nCurrent version is %4$s.\n\nPlease update ADT to the latest version.
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java
index bf14de3..3514db0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/LogCatView.java
@@ -81,6 +81,14 @@ public class LogCatView extends SelectionDependentViewPart {
mLogCatPanel.selectAll();
}
});
+
+ actionBars.setGlobalActionHandler(ActionFactory.FIND.getId(),
+ new Action("Find") {
+ @Override
+ public void run() {
+ mLogCatPanel.showFindDialog();
+ }
+ });
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/.classpath b/eclipse/plugins/com.android.ide.eclipse.gldebugger/.classpath
index ac403f0..59d5fe5 100755
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/.classpath
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/.classpath
@@ -6,5 +6,6 @@
<classpathentry kind="lib" path="libs/host-libprotobuf-java-2.3.0-lite.jar"/>
<classpathentry kind="lib" path="libs/liblzf.jar"/>
<classpathentry combineaccessrules="false" kind="src" path="/ddmlib"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/ddmuilib"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
index 7a9f167..fc99764 100644
--- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/src/com/android/ide/eclipse/gltrace/editors/GLFunctionTraceViewer.java
@@ -16,6 +16,8 @@
package com.android.ide.eclipse.gltrace.editors;
+import com.android.ddmuilib.FindDialog;
+import com.android.ddmuilib.AbstractBufferFindTarget;
import com.android.ide.eclipse.gltrace.GLProtoBuf.GLMessage.Function;
import com.android.ide.eclipse.gltrace.SwtUtils;
import com.android.ide.eclipse.gltrace.TraceFileParserTask;
@@ -28,6 +30,7 @@ import com.android.ide.eclipse.gltrace.views.FrameSummaryViewPage;
import com.android.ide.eclipse.gltrace.views.detail.DetailsPage;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.viewers.CellLabelProvider;
@@ -42,6 +45,9 @@ import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ModifyEvent;
@@ -62,10 +68,12 @@ import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.EditorPart;
import java.io.File;
@@ -80,6 +88,7 @@ public class GLFunctionTraceViewer extends EditorPart implements ISelectionProvi
public static final String ID = "com.android.ide.eclipse.gltrace.GLFunctionTrace"; //$NON-NLS-1$
private static final String DEFAULT_FILTER_MESSAGE = "Filter list of OpenGL calls. Accepts Java regexes.";
+ private static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$
/** Width of thumbnail images of the framebuffer. */
private static final int THUMBNAIL_WIDTH = 50;
@@ -196,6 +205,31 @@ public class GLFunctionTraceViewer extends EditorPart implements ISelectionProvi
refreshUI();
}
});
+
+ IActionBars actionBars = getEditorSite().getActionBars();
+ actionBars.setGlobalActionHandler(ActionFactory.COPY.getId(),
+ new Action("Copy") {
+ @Override
+ public void run() {
+ copySelectionToClipboard();
+ }
+ });
+
+ actionBars.setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(),
+ new Action("Select All") {
+ @Override
+ public void run() {
+ selectAll();
+ }
+ });
+
+ actionBars.setGlobalActionHandler(ActionFactory.FIND.getId(),
+ new Action("Find") {
+ @Override
+ public void run() {
+ showFindDialog();
+ }
+ });
}
private void refreshUI() {
@@ -362,7 +396,7 @@ public class GLFunctionTraceViewer extends EditorPart implements ISelectionProvi
GridData gd = new GridData(GridData.FILL_BOTH);
c.setLayoutData(gd);
- final Tree tree = new Tree(c, SWT.BORDER | SWT.FULL_SELECTION);
+ final Tree tree = new Tree(c, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI);
gd = new GridData(GridData.FILL_BOTH);
tree.setLayoutData(gd);
tree.setLinesVisible(true);
@@ -673,4 +707,79 @@ public class GLFunctionTraceViewer extends EditorPart implements ISelectionProvi
public DetailsPage getDetailsPage() {
return new DetailsPage(mTrace);
}
+
+ private void copySelectionToClipboard() {
+ if (mFrameTreeViewer == null || mFrameTreeViewer.getTree().isDisposed()) {
+ return;
+ }
+
+ StringBuilder sb = new StringBuilder();
+
+ for (TreeItem it: mFrameTreeViewer.getTree().getSelection()) {
+ Object data = it.getData();
+ if (data instanceof GLCallNode) {
+ sb.append(((GLCallNode) data).getCall());
+ sb.append(NEWLINE);
+ }
+ }
+
+ if (sb.length() > 0) {
+ Clipboard cb = new Clipboard(Display.getDefault());
+ cb.setContents(
+ new Object[] { sb.toString() },
+ new Transfer[] { TextTransfer.getInstance() });
+ cb.dispose();
+ }
+ }
+
+ private void selectAll() {
+ if (mFrameTreeViewer == null || mFrameTreeViewer.getTree().isDisposed()) {
+ return;
+ }
+
+ mFrameTreeViewer.getTree().selectAll();
+ }
+
+ private class TraceViewerFindTarget extends AbstractBufferFindTarget {
+ @Override
+ public int getItemCount() {
+ return mFrameTreeViewer.getTree().getItemCount();
+ }
+
+ @Override
+ public String getItem(int index) {
+ Object data = mFrameTreeViewer.getTree().getItem(index).getData();
+ if (data instanceof GLCallNode) {
+ return ((GLCallNode) data).getCall().toString();
+ }
+ return null;
+ }
+
+ @Override
+ public void selectAndReveal(int index) {
+ Tree t = mFrameTreeViewer.getTree();
+ t.deselectAll();
+ t.select(t.getItem(index));
+ t.showSelection();
+ }
+
+ @Override
+ public int getStartingIndex() {
+ return 0;
+ }
+ };
+
+ private FindDialog mFindDialog;
+ private TraceViewerFindTarget mFindTarget = new TraceViewerFindTarget();
+
+ private void showFindDialog() {
+ if (mFindDialog != null) {
+ // the dialog is already displayed
+ return;
+ }
+
+ mFindDialog = new FindDialog(Display.getDefault().getActiveShell(), mFindTarget);
+ mFindDialog.open(); // blocks until find dialog is closed
+ mFindDialog = null;
+ }
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorActionBarAdvisor.java b/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorActionBarAdvisor.java
index 4cf7a94..e31e45e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorActionBarAdvisor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.monitor/src/com/android/ide/eclipse/monitor/MonitorActionBarAdvisor.java
@@ -25,11 +25,14 @@ import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
import org.eclipse.ui.application.ActionBarAdvisor;
import org.eclipse.ui.application.IActionBarConfigurer;
+import org.eclipse.ui.internal.IWorkbenchGraphicConstants;
+import org.eclipse.ui.internal.WorkbenchImages;
public class MonitorActionBarAdvisor extends ActionBarAdvisor {
private IWorkbenchAction mQuitAction;
private IWorkbenchAction mCopyAction;
private IWorkbenchAction mSelectAllAction;
+ private IWorkbenchAction mFindAction;
private IWorkbenchAction mOpenPerspectiveAction;
private IWorkbenchAction mResetPerspectiveAction;
private IWorkbenchAction mPreferencesAction;
@@ -50,6 +53,10 @@ public class MonitorActionBarAdvisor extends ActionBarAdvisor {
mSelectAllAction = ActionFactory.SELECT_ALL.create(window);
register(mSelectAllAction);
+ mFindAction = ActionFactory.FIND.create(window);
+ mFindAction.setText("Find..."); // replace the default "Find and Replace..."
+ register(mFindAction);
+
mOpenPerspectiveAction = ActionFactory.OPEN_PERSPECTIVE_DIALOG.create(window);
register(mOpenPerspectiveAction);
@@ -83,6 +90,7 @@ public class MonitorActionBarAdvisor extends ActionBarAdvisor {
// contents of Edit menu
editMenu.add(mCopyAction);
editMenu.add(mSelectAllAction);
+ editMenu.add(mFindAction);
// contents of Window menu
windowMenu.add(mOpenPerspectiveAction);
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinterTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinterTest.java
index 736931b..731621c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinterTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/formatting/XmlPrettyPrinterTest.java
@@ -236,7 +236,7 @@ public class XmlPrettyPrinterTest extends TestCase {
"]>\n" +
"<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n" +
" android:orientation=\"vertical\" >\n" +
- " <![CDATA[\n" +
+ "<![CDATA[\n" +
"This is character data!\n" +
"<!-- This is not a comment! -->\n" +
"and <this is not an element>\n" +
@@ -850,8 +850,9 @@ public class XmlPrettyPrinterTest extends TestCase {
"<resources>\n" +
"\n" +
" <string name=\"welcome\">Welcome to <b>Android</b>!</string>\n" +
- " <string name=\"glob_settings_top_text\"><b>To install a 24 Clock Widget, please <i>long press</i>\n" +
- " in Home Screen.</b> Configure the Global Settings here.</string>\n" +
+ " <string name=\"glob_settings_top_text\"><b>To install a 24 Clock Widget, " +
+ "please <i>long press</i> in Home Screen.</b> Configure the Global Settings " +
+ "here.</string>\n" +
"\n" +
"</resources>");
}
@@ -915,4 +916,25 @@ public class XmlPrettyPrinterTest extends TestCase {
"\n" +
"</resources>");
}
+
+ public void testComplexString() throws Exception {
+ checkFormat(
+ "res/values/strings.xml",
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<resources>\n" +
+ "<string name=\"progress_completed_export_all\">The database has " +
+ "<b>successfully</b> been exported into: <br /><br /><font size=\"14\">" +
+ "\\\"<i>%s</i>\\\"</font></string>" +
+ "</resources>",
+
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
+ "<resources>\n" +
+ "\n" +
+ " <string name=\"progress_completed_export_all\">The database has " +
+ "<b>successfully</b> been exported into: <br /><br /><font size=\"14\">" +
+ "\\\"<i>%s</i>\\\"</font></string>\n" +
+ "\n" +
+ "</resources>");
+ }
+
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java
index 312df7d..826f36c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/common/layout/LayoutTestBase.java
@@ -16,8 +16,8 @@
package com.android.ide.common.layout;
-import static com.android.util.XmlUtils.ANDROID_URI;
import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
+import static com.android.util.XmlUtils.ANDROID_URI;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
@@ -265,7 +265,8 @@ public class LayoutTestBase extends TestCase {
}
@Override
- public @NonNull IValidator getResourceValidator() {
+ public IValidator getResourceValidator(String resourceTypeName, boolean uniqueInProject,
+ boolean uniqueInLayout, boolean exists, String... allowed) {
fail("Not supported in tests yet");
return null;
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidatorTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidatorTest.java
index 97408c3..af0ba2b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidatorTest.java
+++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceNameValidatorTest.java
@@ -20,6 +20,8 @@ import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
import junit.framework.TestCase;
@@ -61,4 +63,28 @@ public class ResourceNameValidatorTest extends TestCase {
assertTrue(ResourceNameValidator.create(true, ResourceFolderType.DRAWABLE)
.isValid("_foo") != null);
}
+
+ public void testUniqueOrExists() throws Exception {
+ Set<String> existing = new HashSet<String>();
+ existing.add("foo1");
+ existing.add("foo2");
+ existing.add("foo3");
+
+ ResourceNameValidator validator = ResourceNameValidator.create(true, existing,
+ ResourceType.ID);
+ validator.unique();
+
+ assertNull(validator.isValid("foo")); // null: ok (no error message)
+ assertNull(validator.isValid("foo4"));
+ assertNotNull(validator.isValid("foo1"));
+ assertNotNull(validator.isValid("foo2"));
+ assertNotNull(validator.isValid("foo3"));
+
+ validator.exist();
+ assertNotNull(validator.isValid("foo"));
+ assertNotNull(validator.isValid("foo4"));
+ assertNull(validator.isValid("foo1"));
+ assertNull(validator.isValid("foo2"));
+ assertNull(validator.isValid("foo3"));
+ }
}
diff --git a/emulator/opengl/host/tools/emugen/ApiGen.cpp b/emulator/opengl/host/tools/emugen/ApiGen.cpp
index bf2d244..6964862 100644
--- a/emulator/opengl/host/tools/emugen/ApiGen.cpp
+++ b/emulator/opengl/host/tools/emugen/ApiGen.cpp
@@ -418,8 +418,9 @@ static void writeVarEncodingExpression(Var& var, FILE* fp)
} else {
// encode a non pointer variable
if (!var.isVoid()) {
- fprintf(fp, "\t*(%s *) (ptr) = %s; ptr += %u;\n",
- var.type()->name().c_str(), varname,
+ fprintf(fp, "\t\tmemcpy(ptr, &%s, %u); ptr += %u;\n",
+ varname,
+ (uint) var.type()->bytes(),
(uint) var.type()->bytes());
}
}
@@ -570,8 +571,8 @@ int ApiGen::genEncoderImpl(const std::string &filename)
// encode packet header if needed.
if (nvars == 0) {
- fprintf(fp, "\t*(unsigned int *)(ptr) = OP_%s; ptr += 4;\n", e->name().c_str());
- fprintf(fp, "\t*(unsigned int *)(ptr) = (unsigned int) packetSize; ptr += 4;\n");
+ fprintf(fp, "\tint tmp = OP_%s;memcpy(ptr, &tmp, 4); ptr += 4;\n", e->name().c_str());
+ fprintf(fp, "\tmemcpy(ptr, &packetSize, 4); ptr += 4;\n\n");
}
if (maxvars == 0)
@@ -611,8 +612,8 @@ int ApiGen::genEncoderImpl(const std::string &filename)
fprintf(fp, "\t unsigned char *ptr = stream->alloc(packetSize);\n\n");
// encode into the stream;
- fprintf(fp, "\t*(unsigned int *)(ptr) = OP_%s; ptr += 4;\n", e->name().c_str());
- fprintf(fp, "\t*(unsigned int *)(ptr) = (unsigned int) packetSize; ptr += 4;\n\n");
+ fprintf(fp, "\tint tmp = OP_%s; memcpy(ptr, &tmp, 4); ptr += 4;\n", e->name().c_str());
+ fprintf(fp, "\tmemcpy(ptr, &packetSize, 4); ptr += 4;\n\n");
// out variables
for (size_t j = 0; j < nvars; j++) {
diff --git a/emulator/opengl/system/egl/Android.mk b/emulator/opengl/system/egl/Android.mk
index 6778abe..b9c9749 100644
--- a/emulator/opengl/system/egl/Android.mk
+++ b/emulator/opengl/system/egl/Android.mk
@@ -37,6 +37,6 @@ LOCAL_MODULE_TAGS := debug
LOCAL_MODULE_CLASS := ETC
include $(BUILD_PREBUILT)
-endif # TARGET_PRODUCT in 'full sdk full_x86 sdk_x86 google_sdk google_sdk_x86)
+endif # TARGET_PRODUCT in 'full sdk full_x86 full_mips sdk_x86 sdk_mips google_sdk google_sdk_x86 google_sdk_mips)
endif # BUILD_EMULATOR_OPENGL_DRIVER != false
diff --git a/emulator/opengl/tests/gles_android_wrapper/Android.mk b/emulator/opengl/tests/gles_android_wrapper/Android.mk
index f7c8fed..f5254b7 100644
--- a/emulator/opengl/tests/gles_android_wrapper/Android.mk
+++ b/emulator/opengl/tests/gles_android_wrapper/Android.mk
@@ -48,7 +48,7 @@ $(call emugl-end-module)
# Other builds are device-specific and will provide their own
# version of this file to point to the appropriate HW EGL libraries.
#
-ifneq (,$(filter full full_x86 sdk sdk_x86,$(TARGET_PRODUCT)))
+ifneq (,$(filter full full_x86 full_mips sdk sdk_x86 sdk_mips,$(TARGET_PRODUCT)))
ifeq (,$(BUILD_EMULATOR_OPENGL_DRIVER))
include $(CLEAR_VARS)
@@ -61,7 +61,7 @@ LOCAL_MODULE_CLASS := ETC
include $(BUILD_PREBUILT)
endif # building 'real' driver BUILD_EMULATOR_OPENGL_DRIVER
-endif # TARGET_PRODUCT in 'full sdk full_x86 sdk_x86'
+endif # TARGET_PRODUCT in 'full sdk full_x86 sdk_x86 full_mips sdk_mips'
#### gles_emul.cfg ####
include $(CLEAR_VARS)
diff --git a/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk b/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk
index d47d340..bce56e3 100644
--- a/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk
+++ b/emulator/opengl/tests/translator_tests/GLES_CM/Android.mk
@@ -9,12 +9,9 @@ LOCAL_SDL_CFLAGS := $(shell $(LOCAL_SDL_CONFIG) --cflags)
LOCAL_SDL_LDLIBS := $(filter-out %.a %.lib,$(shell $(LOCAL_SDL_CONFIG) --static-libs))
ifeq ($(HOST_OS),darwin)
- DARWIN_VERSION := $(strip $(shell sw_vers -productVersion))
- ifneq ($(filter 10.7 10.7.% 10.8 10.8.%,$(DARWIN_VERSION)),)
- # OS X 10.7+ needs to be forced to link dylib to avoid problems
- # with the dynamic function lookups in SDL 1.2
- LOCAL_SDL_LDLIBS += /usr/lib/dylib1.o
- endif
+ # OS X 10.6+ needs to be forced to link dylib to avoid problems
+ # with the dynamic function lookups in SDL 1.2
+ LOCAL_SDL_LDLIBS += /usr/lib/dylib1.o
endif
LOCAL_SRC_FILES:= \
diff --git a/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk b/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk
index 2371da7..504530f 100644
--- a/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk
+++ b/emulator/opengl/tests/translator_tests/GLES_V2/Android.mk
@@ -17,13 +17,10 @@ LOCAL_LDLIBS += $(LOCAL_SDL_LDLIBS)
LOCAL_STATIC_LIBRARIES += libSDL libSDLmain
ifeq ($(HOST_OS),darwin)
-DARWIN_VERSION := $(strip $(shell sw_vers -productVersion))
-ifneq ($(filter 10.7 10.7.% 10.8 10.8.%,$(DARWIN_VERSION)),)
- # OS X 10.7+ needs to be forced to link dylib to avoid problems
+ # OS X 10.6+ needs to be forced to link dylib to avoid problems
# with the dynamic function lookups in SDL 1.2
LOCAL_LDLIBS += /usr/lib/dylib1.o
-endif
-$(call emugl-import,libMac_view)
+ $(call emugl-import,libMac_view)
endif
$(call emugl-end-module)
diff --git a/rule_api/src/com/android/ide/common/api/IClientRulesEngine.java b/rule_api/src/com/android/ide/common/api/IClientRulesEngine.java
index b9ea6cb..329f38c 100644
--- a/rule_api/src/com/android/ide/common/api/IClientRulesEngine.java
+++ b/rule_api/src/com/android/ide/common/api/IClientRulesEngine.java
@@ -106,11 +106,25 @@ public interface IClientRulesEngine {
/**
* Returns a resource name validator for the current project
*
- * @return an {@link IValidator} for validating a new resource name in the current
- * project
+ * @param resourceTypeName resource type, such as "id", "string", and so on
+ * @param uniqueInProject if true, the resource name must be unique in the
+ * project (not already be defined anywhere else)
+ * @param uniqueInLayout if true, the resource name must be unique at least
+ * within the current layout. This only applies to {@code @id}
+ * resources since only those resources can be defined in-place
+ * within a layout
+ * @param exists if true, the resource name must already exist
+ * @param allowed allowed names (optional). This can for example be used to
+ * request a unique-in-layout validator, but to remove the
+ * current value of the node being edited from consideration such
+ * that it allows you to leave the value the same
+ * @return an {@link IValidator} for validating a new resource name in the
+ * current project
*/
@Nullable
- IValidator getResourceValidator();
+ IValidator getResourceValidator(@NonNull String resourceTypeName,
+ boolean uniqueInProject, boolean uniqueInLayout, boolean exists,
+ String... allowed);
/**
* Displays an input dialog where the user can enter an Android reference value
@@ -119,7 +133,7 @@ public interface IClientRulesEngine {
* @return the reference selected by the user, or null
*/
@Nullable
- String displayReferenceInput(String currentValue);
+ String displayReferenceInput(@Nullable String currentValue);
/**
* Displays an input dialog where the user can enter an Android resource name of the
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/globals.xml.ftl b/templates/activities/BlankActivity/globals.xml.ftl
index 3a26abd..3a26abd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/globals.xml.ftl
+++ b/templates/activities/BlankActivity/globals.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/recipe.xml.ftl b/templates/activities/BlankActivity/recipe.xml.ftl
index 2ce72db..2ce72db 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/recipe.xml.ftl
+++ b/templates/activities/BlankActivity/recipe.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/AndroidManifest.xml.ftl b/templates/activities/BlankActivity/root/AndroidManifest.xml.ftl
index ffcce79..ffcce79 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/AndroidManifest.xml.ftl
+++ b/templates/activities/BlankActivity/root/AndroidManifest.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-hdpi/ic_action_search.png b/templates/activities/BlankActivity/root/res/drawable-hdpi/ic_action_search.png
index 67de12d..67de12d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-hdpi/ic_action_search.png
+++ b/templates/activities/BlankActivity/root/res/drawable-hdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-mdpi/ic_action_search.png b/templates/activities/BlankActivity/root/res/drawable-mdpi/ic_action_search.png
index 134d549..134d549 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-mdpi/ic_action_search.png
+++ b/templates/activities/BlankActivity/root/res/drawable-mdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png b/templates/activities/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png
index d699c6b..d699c6b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png
+++ b/templates/activities/BlankActivity/root/res/drawable-xhdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_fragment_container.xml b/templates/activities/BlankActivity/root/res/layout/activity_fragment_container.xml
index 3128b5f..3128b5f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_fragment_container.xml
+++ b/templates/activities/BlankActivity/root/res/layout/activity_fragment_container.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_pager.xml.ftl b/templates/activities/BlankActivity/root/res/layout/activity_pager.xml.ftl
index c8f1604..c8f1604 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_pager.xml.ftl
+++ b/templates/activities/BlankActivity/root/res/layout/activity_pager.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_simple.xml b/templates/activities/BlankActivity/root/res/layout/activity_simple.xml
index aa34ee3..aa34ee3 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/layout/activity_simple.xml
+++ b/templates/activities/BlankActivity/root/res/layout/activity_simple.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/menu/main.xml b/templates/activities/BlankActivity/root/res/menu/main.xml
index cfc10fd..cfc10fd 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/menu/main.xml
+++ b/templates/activities/BlankActivity/root/res/menu/main.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values-large/dimens.xml b/templates/activities/BlankActivity/root/res/values-large/dimens.xml
index d8cd7c2..d8cd7c2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values-large/dimens.xml
+++ b/templates/activities/BlankActivity/root/res/values-large/dimens.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/dimens.xml b/templates/activities/BlankActivity/root/res/values/dimens.xml
index d95a70f..d95a70f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/dimens.xml
+++ b/templates/activities/BlankActivity/root/res/values/dimens.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/strings.xml.ftl b/templates/activities/BlankActivity/root/res/values/strings.xml.ftl
index 753649d..753649d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/res/values/strings.xml.ftl
+++ b/templates/activities/BlankActivity/root/res/values/strings.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/DropdownActivity.java.ftl b/templates/activities/BlankActivity/root/src/app_package/DropdownActivity.java.ftl
index 98c1a8f..98c1a8f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/DropdownActivity.java.ftl
+++ b/templates/activities/BlankActivity/root/src/app_package/DropdownActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/SimpleActivity.java.ftl b/templates/activities/BlankActivity/root/src/app_package/SimpleActivity.java.ftl
index 1ebc0fa..1ebc0fa 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/SimpleActivity.java.ftl
+++ b/templates/activities/BlankActivity/root/src/app_package/SimpleActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsActivity.java.ftl b/templates/activities/BlankActivity/root/src/app_package/TabsActivity.java.ftl
index ab11a7f..ab11a7f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsActivity.java.ftl
+++ b/templates/activities/BlankActivity/root/src/app_package/TabsActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl b/templates/activities/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl
index eb47519..eb47519 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl
+++ b/templates/activities/BlankActivity/root/src/app_package/TabsAndPagerActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml b/templates/activities/BlankActivity/template.xml
index 302e2cc..10e6bc8 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template.xml
+++ b/templates/activities/BlankActivity/template.xml
@@ -20,7 +20,7 @@
type="string"
constraints="layout|unique"
suggest="${activityToLayout(activityClass)}"
- default="main"
+ default="activity_main"
help="The name of the layout to create for the activity" />
<parameter
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity.png b/templates/activities/BlankActivity/template_blank_activity.png
index 729dd1c..729dd1c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity.png
+++ b/templates/activities/BlankActivity/template_blank_activity.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_dropdown.png b/templates/activities/BlankActivity/template_blank_activity_dropdown.png
index 09fa2cf..09fa2cf 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_dropdown.png
+++ b/templates/activities/BlankActivity/template_blank_activity_dropdown.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_pager.png b/templates/activities/BlankActivity/template_blank_activity_pager.png
index 7cd8e0e..7cd8e0e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_pager.png
+++ b/templates/activities/BlankActivity/template_blank_activity_pager.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs.png b/templates/activities/BlankActivity/template_blank_activity_tabs.png
index 86a09d6..86a09d6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs.png
+++ b/templates/activities/BlankActivity/template_blank_activity_tabs.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs_pager.png b/templates/activities/BlankActivity/template_blank_activity_tabs_pager.png
index 0697a56..0697a56 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/BlankActivity/template_blank_activity_tabs_pager.png
+++ b/templates/activities/BlankActivity/template_blank_activity_tabs_pager.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/globals.xml.ftl b/templates/activities/MasterDetailFlow/globals.xml.ftl
index 519c081..519c081 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/globals.xml.ftl
+++ b/templates/activities/MasterDetailFlow/globals.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/recipe.xml.ftl b/templates/activities/MasterDetailFlow/recipe.xml.ftl
index a07635e..a07635e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/recipe.xml.ftl
+++ b/templates/activities/MasterDetailFlow/recipe.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/AndroidManifest.xml.ftl b/templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl
index 1b9aa76..1b9aa76 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/AndroidManifest.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/AndroidManifest.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl
index 1d6d5dc..1d6d5dc 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_detail.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl
index 788e763..788e763 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_list.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl
index c7a2c75..c7a2c75 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/layout/activity_content_twopane.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl b/templates/activities/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl
index 9b7ca72..9b7ca72 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/layout/fragment_content_detail.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-large/refs.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl
index f3edd90..f3edd90 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-large/refs.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/values-large/refs.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
index f3edd90..f3edd90 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/values-sw600dp/refs.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values/strings.xml.ftl b/templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl
index 9b92c7d..9b92c7d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/res/values/strings.xml.ftl
+++ b/templates/activities/MasterDetailFlow/root/res/values/strings.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl
index a7deaf6..a7deaf6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl
+++ b/templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl
index a0acb1c..a0acb1c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl
+++ b/templates/activities/MasterDetailFlow/root/src/app_package/ContentDetailFragment.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl
index 4bc5216..4bc5216 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl
+++ b/templates/activities/MasterDetailFlow/root/src/app_package/ContentListActivity.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl
index 6b4b9a0..6b4b9a0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl
+++ b/templates/activities/MasterDetailFlow/root/src/app_package/ContentListFragment.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl b/templates/activities/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl
index 2b05416..2b05416 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl
+++ b/templates/activities/MasterDetailFlow/root/src/app_package/dummy/DummyContent.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml b/templates/activities/MasterDetailFlow/template.xml
index 0eed682..0eed682 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template.xml
+++ b/templates/activities/MasterDetailFlow/template.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template_master_detail.png b/templates/activities/MasterDetailFlow/template_master_detail.png
index f9d3f23..f9d3f23 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/MasterDetailFlow/template_master_detail.png
+++ b/templates/activities/MasterDetailFlow/template_master_detail.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/globals.xml.ftl b/templates/other/CustomView/globals.xml.ftl
index d2eeb40..d2eeb40 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/globals.xml.ftl
+++ b/templates/other/CustomView/globals.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/recipe.xml.ftl b/templates/other/CustomView/recipe.xml.ftl
index d152df0..d152df0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/recipe.xml.ftl
+++ b/templates/other/CustomView/recipe.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/layout/sample.xml.ftl b/templates/other/CustomView/root/res/layout/sample.xml.ftl
index bdd8c8b..bdd8c8b 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/layout/sample.xml.ftl
+++ b/templates/other/CustomView/root/res/layout/sample.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/values/attrs.xml.ftl b/templates/other/CustomView/root/res/values/attrs.xml.ftl
index 89059d2..89059d2 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/res/values/attrs.xml.ftl
+++ b/templates/other/CustomView/root/res/values/attrs.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/src/app_package/CustomView.java.ftl b/templates/other/CustomView/root/src/app_package/CustomView.java.ftl
index e1c7e13..e1c7e13 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/root/src/app_package/CustomView.java.ftl
+++ b/templates/other/CustomView/root/src/app_package/CustomView.java.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/template.xml b/templates/other/CustomView/template.xml
index 9511566..9511566 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/CustomView/template.xml
+++ b/templates/other/CustomView/template.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/globals.xml.ftl b/templates/projects/NewAndroidApplication/globals.xml.ftl
index bfc27eb..bfc27eb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/globals.xml.ftl
+++ b/templates/projects/NewAndroidApplication/globals.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/recipe.xml.ftl b/templates/projects/NewAndroidApplication/recipe.xml.ftl
index b343a10..b343a10 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/recipe.xml.ftl
+++ b/templates/projects/NewAndroidApplication/recipe.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/AndroidManifest.xml.ftl b/templates/projects/NewAndroidApplication/root/AndroidManifest.xml.ftl
index c97c601..c97c601 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/AndroidManifest.xml.ftl
+++ b/templates/projects/NewAndroidApplication/root/AndroidManifest.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png b/templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png
index 67de12d..67de12d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png
+++ b/templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png b/templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png
index fba1ff0..fba1ff0 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png
+++ b/templates/projects/NewAndroidApplication/root/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png b/templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png
index 134d549..134d549 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png
+++ b/templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png b/templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png
index 72a445d..72a445d 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png
+++ b/templates/projects/NewAndroidApplication/root/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png b/templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png
index d699c6b..d699c6b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png
+++ b/templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_action_search.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png b/templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png
index 002e7b0..002e7b0 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png
+++ b/templates/projects/NewAndroidApplication/root/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values-large/dimens.xml b/templates/projects/NewAndroidApplication/root/res/values-large/dimens.xml
index d8cd7c2..d8cd7c2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values-large/dimens.xml
+++ b/templates/projects/NewAndroidApplication/root/res/values-large/dimens.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/dimens.xml b/templates/projects/NewAndroidApplication/root/res/values/dimens.xml
index d95a70f..d95a70f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/dimens.xml
+++ b/templates/projects/NewAndroidApplication/root/res/values/dimens.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/strings.xml.ftl b/templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl
index 557e5c2..557e5c2 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/strings.xml.ftl
+++ b/templates/projects/NewAndroidApplication/root/res/values/strings.xml.ftl
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/styles.xml b/templates/projects/NewAndroidApplication/root/res/values/styles.xml
index 5cd7c2f..5cd7c2f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/root/res/values/styles.xml
+++ b/templates/projects/NewAndroidApplication/root/res/values/styles.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml b/templates/projects/NewAndroidApplication/template.xml
index 84ba6c7..84ba6c7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template.xml
+++ b/templates/projects/NewAndroidApplication/template.xml
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template_new_project.png b/templates/projects/NewAndroidApplication/template_new_project.png
index 92e8556..92e8556 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/NewAndroidApplication/template_new_project.png
+++ b/templates/projects/NewAndroidApplication/template_new_project.png
Binary files differ
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/templates/res/android-support-v4.jar.bin b/templates/resources/android-support-v4.jar.bin
index d006198..d006198 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/templates/res/android-support-v4.jar.bin
+++ b/templates/resources/android-support-v4.jar.bin
Binary files differ