diff options
120 files changed, 1771 insertions, 1307 deletions
diff --git a/adtproductbuild/Android.mk b/adtproductbuild/Android.mk index 124eafb..2148cdf 100644 --- a/adtproductbuild/Android.mk +++ b/adtproductbuild/Android.mk @@ -121,7 +121,9 @@ $(5): $(ADT_IDE_JAVA_TARGET) $(4)/eclipse/plugins/com.android.ide.eclipse.adt.package_*/about.mappings && \ sed -i -e 's/org.eclipse.platform.ide/com.android.ide.eclipse.adt.package.product/g' \ -e 's/org.eclipse.platform/com.android.ide.eclipse.adt.package/g' \ - $(4)/eclipse/configuration/config.ini + $(4)/eclipse/configuration/config.ini && \ + echo "-XX:MaxPermSize=512M" >> \ + $(4)/eclipse/$(if $(filter macosx.cocoa,$(1)),Eclipse.app/Contents/MacOS/)eclipse.ini $(hide)cd $(4) && zip -9rq ../$(notdir $(5)) eclipse ifneq (,$(ADT_IDE_DEST_DIR)) $(ADT_IDE_DEST_DIR)/$(notdir $(5)): $(5) diff --git a/adtproductbuild/build.xml b/adtproductbuild/build.xml index 4c5cbb9..3b53823 100644 --- a/adtproductbuild/build.xml +++ b/adtproductbuild/build.xml @@ -100,15 +100,15 @@ <mkdir dir="${targetDir}/deltapack" /> <mkdir dir="${targetDir}/repos" /> - <unzip src="${deltaPackTargetSrcDir}/deltapack/eclipse-4.2.2-delta-pack.zip" dest="${targetDir}/deltapack" overwrite="false" /> - <unzip src="${targetSrcDir}/platform/org.eclipse.platform-4.2.2.zip" dest="${targetDir}/repos/platform" overwrite="false" /> - <unzip src="${targetSrcDir}/cdt/cdt-master-8.0.2.zip" dest="${targetDir}/repos/cdt" overwrite="false" /> - <unzip src="${targetSrcDir}/emf/emf-xsd-SDK-M201201231045.zip" dest="${targetDir}/repos/emf" overwrite="false" /> - <unzip src="${targetSrcDir}/jdt/org.eclipse.jdt.source-4.2.2.zip" dest="${targetDir}/repos/jdt" overwrite="false" /> - <unzip src="${targetSrcDir}/wtp/wtp-repo-R-3.3.2-20120210195245.zip" dest="${targetDir}/repos/wtp" overwrite="false" /> - <unzip src="${targetSrcDir}/gef/GEF-SDK-3.7.2.zip" dest="${targetDir}/repos/gef" overwrite="false" /> - <unzip src="${targetSrcDir}/pde/org.eclipse.pde-3.8.zip" dest="${targetDir}/repos/pde" overwrite="false" /> - <unzip src="${targetSrcDir}/egit/org.eclipse.egit.repository-2.2.0.201212191850-r.zip" dest="${targetDir}/repos/egit" overwrite="false" /> + <unzip src="${deltaPackTargetSrcDir}/deltapack/eclipse-4.3.1-delta-pack.zip" dest="${targetDir}/deltapack" overwrite="false" /> + <unzip src="${targetSrcDir}/platform/org.eclipse.platform-4.3.1.zip" dest="${targetDir}/repos/platform" overwrite="false" /> + <unzip src="${targetSrcDir}/cdt/cdt-master-8.2.1.zip" dest="${targetDir}/repos/cdt" overwrite="false" /> + <unzip src="${targetSrcDir}/emf/emf-xsd-SDK-2.9.1.zip" dest="${targetDir}/repos/emf" overwrite="false" /> + <unzip src="${targetSrcDir}/jdt/org.eclipse.jdt.source-4.3.1.zip" dest="${targetDir}/repos/jdt" overwrite="false" /> + <unzip src="${targetSrcDir}/wtp/wtp4x-repo-R-3.5.1-20130913223750.zip" dest="${targetDir}/repos/wtp" overwrite="false" /> + <unzip src="${targetSrcDir}/gef/GEF-SDK-3.9.1RC1.zip" dest="${targetDir}/repos/gef" overwrite="false" /> + <unzip src="${targetSrcDir}/pde/org.eclipse.pde-4.3.1.zip" dest="${targetDir}/repos/pde" overwrite="false" /> + <unzip src="${targetSrcDir}/egit/org.eclipse.egit.repository-3.1.0.201310021548-r.zip" dest="${targetDir}/repos/egit" overwrite="false" /> </target> <target name="create-translation-target" if="translation.plugin.present"> diff --git a/apkbuilder/etc/apkbuilder.bat b/apkbuilder/etc/apkbuilder.bat index c82f01d..3375b85 100755 --- a/apkbuilder/etc/apkbuilder.bat +++ b/apkbuilder/etc/apkbuilder.bat @@ -30,16 +30,16 @@ call lib\find_java.bat if not defined java_exe goto :EOF set jarfile=sdklib.jar -set frameworkdir= +set frameworkdir=. -if exist %frameworkdir%%jarfile% goto JarFileOk - set frameworkdir=lib\ +if exist %frameworkdir%\%jarfile% goto JarFileOk + set frameworkdir=lib -if exist %frameworkdir%%jarfile% goto JarFileOk - set frameworkdir=..\framework\ +if exist %frameworkdir%\%jarfile% goto JarFileOk + set frameworkdir=..\framework :JarFileOk -set jarpath=%frameworkdir%%jarfile% +set jarpath=%frameworkdir%\%jarfile% -call %java_exe% -classpath %jarpath% com.android.sdklib.build.ApkBuilderMain %* +call "%java_exe%" -classpath "%jarpath%" com.android.sdklib.build.ApkBuilderMain %* diff --git a/bash_completion/adb.bash b/bash_completion/adb.bash index 46ed208..d4d7b4e 100644 --- a/bash_completion/adb.bash +++ b/bash_completion/adb.bash @@ -78,6 +78,9 @@ _adb() { install) _adb_cmd_install "$serial" $i ;; + sideload) + _adb_cmd_sideload "$serial" $i + ;; pull) _adb_cmd_pull "$serial" $i ;; @@ -133,6 +136,17 @@ _adb_cmd_install() { _adb_util_complete_local_file "${cur}" '!*.apk' } +_adb_cmd_sideload() { + local serial i cur + + serial=$1 + i=$2 + + cur="${COMP_WORDS[COMP_CWORD]}" + + _adb_util_complete_local_file "${cur}" '!*.zip' +} + _adb_cmd_push() { local serial IFS=$'\n' i cur diff --git a/build/product_sdk.mk b/build/product_sdk.mk index 6e937ed..0587656 100644 --- a/build/product_sdk.mk +++ b/build/product_sdk.mk @@ -30,7 +30,6 @@ PRODUCT_PACKAGES += \ ant-glob \ annotations \ mksdcard \ - monitor \ fastboot \ emugen diff --git a/build/tools.atree b/build/tools.atree index 45f44c9..801c4a6 100644 --- a/build/tools.atree +++ b/build/tools.atree @@ -24,7 +24,7 @@ prebuilts/devtools/tools/lib tools/lib # manual copy of lombok-ast for now -prebuilts/tools/common/lombok-ast/lombok-ast-0.2.1.jar tools/lib/lombok-ast-0.2.1.jar +prebuilts/tools/common/lombok-ast/lombok-ast-0.2.1.jar tools/lib/lombok-ast.jar prebuilts/tools/common/lombok-ast/LICENSE.txt tools/lib/lombok-ast-NOTICE.txt prebuilts/devtools/tools/android tools/android diff --git a/build/tools.darwin.atree b/build/tools.darwin.atree index d584231..c37480b 100644 --- a/build/tools.darwin.atree +++ b/build/tools.darwin.atree @@ -22,9 +22,9 @@ # Tools Component ############################################################################## -# RCP Monitor. -bin/monitor tools/monitor -eclipse/monitor-macosx.cocoa.x86_64/monitor tools/lib/monitor-x86_64 +# RCP Monitor. Temporarily disabled: See b/8992787 +#bin/monitor tools/monitor +#eclipse/monitor-macosx.cocoa.x86_64/monitor tools/lib/monitor-x86_64 # swt prebuilts/tools/darwin-x86/swt/swt.jar tools/lib/x86/swt.jar diff --git a/build/tools.linux.atree b/build/tools.linux.atree index cdba1f2..58f3576 100644 --- a/build/tools.linux.atree +++ b/build/tools.linux.atree @@ -22,10 +22,10 @@ # Tools Component ############################################################################## -# RCP Monitor. -bin/monitor tools/monitor -eclipse/monitor-linux.gtk.x86/monitor tools/lib/monitor-x86 -eclipse/monitor-linux.gtk.x86_64/monitor tools/lib/monitor-x86_64 +# RCP Monitor. Temporarily disabled: See b/8992787 +#bin/monitor tools/monitor +#eclipse/monitor-linux.gtk.x86/monitor tools/lib/monitor-x86 +#eclipse/monitor-linux.gtk.x86_64/monitor tools/lib/monitor-x86_64 # swt diff --git a/build/tools.windows.atree b/build/tools.windows.atree index 5e5e766..36a6feb 100755 --- a/build/tools.windows.atree +++ b/build/tools.windows.atree @@ -93,12 +93,13 @@ rm tools/zipalign bin/zipalign.exe strip tools/zipalign.exe # RCP Monitor. Remove linux stuff and replace by Windows files. -rm tools/monitor -rm tools/lib/monitor-x86 -rm tools/lib/monitor-x86_64 -sdk/monitor/monitor.bat tools/monitor.bat -eclipse/monitor-win32.win32.x86/monitor tools/lib/monitor-x86 -eclipse/monitor-win32.win32.x86_64/monitor tools/lib/monitor-x86_64 +# Temporarily disabled: See b/8992787 +#rm tools/monitor +#rm tools/lib/monitor-x86 +#rm tools/lib/monitor-x86_64 +#sdk/monitor/monitor.bat tools/monitor.bat +#eclipse/monitor-win32.win32.x86/monitor tools/lib/monitor-x86 +#eclipse/monitor-win32.win32.x86_64/monitor tools/lib/monitor-x86_64 # Copy the AVD & SDK Manager (aka avd/sdklauncher) to the root of the SDK as diff --git a/build/windows_sdk_tools.mk b/build/windows_sdk_tools.mk index ee4ca7f..80f00c0 100644 --- a/build/windows_sdk_tools.mk +++ b/build/windows_sdk_tools.mk @@ -14,7 +14,6 @@ WIN_SDK_TARGETS := \ find_java \ find_lock \ mksdcard \ - monitor \ sdklauncher @@ -29,6 +28,7 @@ endif # Define the list of tool-dependent modules requisites needed # for the Windows SDK. These will be built using HOST_OS=linux. -WIN_SDK_BUILD_PREREQ := \ - monitor +# Temporarily disabled: See b/8992787 +#WIN_SDK_BUILD_PREREQ := \ +# monitor diff --git a/build/windows_sdk_whitelist.mk b/build/windows_sdk_whitelist.mk index f10545e..40b70e5 100644 --- a/build/windows_sdk_whitelist.mk +++ b/build/windows_sdk_whitelist.mk @@ -47,7 +47,6 @@ subdirs += \ external/junit \ sdk/apkbuilder \ sdk/eclipse/scripts/rcp \ - sdk/monitor \ sdk/testutils else diff --git a/changes.txt b/changes.txt index 1649586..d4ca45d 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,12 @@ Change log for Android SDK Tools. +Revision 22.2.1: +- Emergency fix to new project templates. + +Revision 22.2.0: + +Revision 22: + Revision 20: - Ant build system: - Ant build system: diff --git a/eclipse/dictionary.txt b/eclipse/dictionary.txt index bc901fa..0dc00fd 100644 --- a/eclipse/dictionary.txt +++ b/eclipse/dictionary.txt @@ -258,6 +258,7 @@ risky rollback rowspan rowspans +sandbox sans scrollable scrollbar diff --git a/eclipse/features/com.android.ide.eclipse.adt.package/feature.xml b/eclipse/features/com.android.ide.eclipse.adt.package/feature.xml index 8e69281..ec3843b 100644 --- a/eclipse/features/com.android.ide.eclipse.adt.package/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.adt.package/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.adt.package" label="ADT Package" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project" plugin="com.android.ide.eclipse.adt.package"> @@ -73,12 +73,12 @@ <import plugin="org.eclipse.cdt.dsf.gdb.ui"/> <import plugin="org.eclipse.cdt.launch"/> <import feature="org.eclipse.egit" /> - <import feature="com.android.ide.eclipse.ddms" version="22.0.0" match="greaterOrEqual" /> - <import feature="com.android.ide.eclipse.adt" version="22.0.0" match="greaterOrEqual" /> - <import feature="com.android.ide.eclipse.gldebugger" version="22.0.0" match="greaterOrEqual" /> - <import feature="com.android.ide.eclipse.hierarchyviewer" version="22.0.0" match="greaterOrEqual" /> - <import feature="com.android.ide.eclipse.ndk" version="22.0.0" match="greaterOrEqual" /> - <import feature="com.android.ide.eclipse.traceview" version="22.0.0" match="greaterOrEqual" /> + <import feature="com.android.ide.eclipse.ddms" version="22.2.0" match="greaterOrEqual" /> + <import feature="com.android.ide.eclipse.adt" version="22.2.0" match="greaterOrEqual" /> + <import feature="com.android.ide.eclipse.gldebugger" version="22.2.0" match="greaterOrEqual" /> + <import feature="com.android.ide.eclipse.hierarchyviewer" version="22.2.0" match="greaterOrEqual" /> + <import feature="com.android.ide.eclipse.ndk" version="22.2.0" match="greaterOrEqual" /> + <import feature="com.android.ide.eclipse.traceview" version="22.2.0" match="greaterOrEqual" /> <!-- The build scripts will pull in the translation plugin if its plugin repository is accessible. The following line should remain without any modifications as the build script looks for diff --git a/eclipse/features/com.android.ide.eclipse.adt/feature.xml b/eclipse/features/com.android.ide.eclipse.adt/feature.xml index 2f149c2..f90725c 100644 --- a/eclipse/features/com.android.ide.eclipse.adt/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.adt/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.adt" label="Android Development Tools" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project" plugin="com.android.ide.eclipse.adt"> diff --git a/eclipse/features/com.android.ide.eclipse.ddms/feature.xml b/eclipse/features/com.android.ide.eclipse.ddms/feature.xml index 965161d..3efcab4 100644 --- a/eclipse/features/com.android.ide.eclipse.ddms/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.ddms/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.ddms" label="Android DDMS" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project" plugin="com.android.ide.eclipse.ddms"> diff --git a/eclipse/features/com.android.ide.eclipse.gldebugger/feature.xml b/eclipse/features/com.android.ide.eclipse.gldebugger/feature.xml index f84addf..dda3e0c 100644 --- a/eclipse/features/com.android.ide.eclipse.gldebugger/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.gldebugger/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.gldebugger" label="Tracer for OpenGL ES" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project"> <description> diff --git a/eclipse/features/com.android.ide.eclipse.hierarchyviewer/feature.xml b/eclipse/features/com.android.ide.eclipse.hierarchyviewer/feature.xml index 2ffc7fd..ea14352 100644 --- a/eclipse/features/com.android.ide.eclipse.hierarchyviewer/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.hierarchyviewer/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.hierarchyviewer" label="Android Hierarchy Viewer" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project" plugin="com.android.ide.eclipse.hierarchyviewer"> diff --git a/eclipse/features/com.android.ide.eclipse.ndk/feature.xml b/eclipse/features/com.android.ide.eclipse.ndk/feature.xml index 3973c64..2ca0a61 100644 --- a/eclipse/features/com.android.ide.eclipse.ndk/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.ndk/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.ndk" label="Android Native Development Tools" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project"> <description> diff --git a/eclipse/features/com.android.ide.eclipse.pdt/feature.xml b/eclipse/features/com.android.ide.eclipse.pdt/feature.xml index 940a540..bd3f876 100644 --- a/eclipse/features/com.android.ide.eclipse.pdt/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.pdt/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.pdt" label="Android Platform Development Tools" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project"> <description> diff --git a/eclipse/features/com.android.ide.eclipse.tests/feature.xml b/eclipse/features/com.android.ide.eclipse.tests/feature.xml index c2577dd..932822d 100644 --- a/eclipse/features/com.android.ide.eclipse.tests/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.tests/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.tests" label="ADT Tests" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project"> <copyright> diff --git a/eclipse/features/com.android.ide.eclipse.traceview/feature.xml b/eclipse/features/com.android.ide.eclipse.traceview/feature.xml index 0290107..37bf9a4 100644 --- a/eclipse/features/com.android.ide.eclipse.traceview/feature.xml +++ b/eclipse/features/com.android.ide.eclipse.traceview/feature.xml @@ -2,7 +2,7 @@ <feature id="com.android.ide.eclipse.traceview" label="Android Traceview" - version="22.0.0.qualifier" + version="22.3.0.qualifier" provider-name="The Android Open Source Project" plugin="com.android.ide.eclipse.traceview"> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt.overlay/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt.overlay/META-INF/MANIFEST.MF index 2317daa..8ba1dcd 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt.overlay/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.adt.overlay/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: ADT XML Overlay Bundle-SymbolicName: overlay.com.android.ide.eclipse.adt.overlay;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Vendor: The Android Open Source Project Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, diff --git a/eclipse/plugins/com.android.ide.eclipse.adt.package/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt.package/META-INF/MANIFEST.MF index bdbc7ea..010bf28 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt.package/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.adt.package/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: ADT Package Bundle-SymbolicName: com.android.ide.eclipse.adt.package;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Vendor: The Android Open Source Project Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Require-Bundle: org.eclipse.platform, diff --git a/eclipse/plugins/com.android.ide.eclipse.adt.package/ide.product b/eclipse/plugins/com.android.ide.eclipse.adt.package/ide.product index 0597324..b532c53 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt.package/ide.product +++ b/eclipse/plugins/com.android.ide.eclipse.adt.package/ide.product @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <?pde version="3.5"?> -<product name="Android Developer Tools" uid="com.android.ide.eclipse.adt.package.product" id="com.android.ide.eclipse.adt.package.product" application="org.eclipse.ui.ide.workbench" version="22.0.0.qualifier" useFeatures="true" includeLaunchers="true"> +<product name="Android Developer Tools" uid="com.android.ide.eclipse.adt.package.product" id="com.android.ide.eclipse.adt.package.product" application="org.eclipse.ui.ide.workbench" version="22.3.0.qualifier" useFeatures="true" includeLaunchers="true"> <configIni use="default"> </configIni> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF index 1683324..bd72b31 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Android Development Toolkit Bundle-SymbolicName: com.android.ide.eclipse.adt;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-ClassPath: ., libs/sdkuilib.jar, libs/ninepatch.jar, diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java index a453147..46770e8 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/common/layout/grid/GridModel.java @@ -867,8 +867,16 @@ public class GridModel { public static Pair<int[], int[]> getAxisBounds(Object view) { try { Class<?> clz = view.getClass(); - Field horizontalAxis = clz.getDeclaredField("horizontalAxis"); //$NON-NLS-1$ - Field verticalAxis = clz.getDeclaredField("verticalAxis"); //$NON-NLS-1$ + String verticalAxisName = "verticalAxis"; + Field horizontalAxis; + try { + horizontalAxis = clz.getDeclaredField("horizontalAxis"); //$NON-NLS-1$ + } catch (NoSuchFieldException e) { + // Field names changed in KitKat + horizontalAxis = clz.getDeclaredField("mHorizontalAxis"); //$NON-NLS-1$ + verticalAxisName = "mVerticalAxis"; + } + Field verticalAxis = clz.getDeclaredField(verticalAxisName); horizontalAxis.setAccessible(true); verticalAxis.setAccessible(true); Object horizontal = horizontalAxis.get(view); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java index 5330e08..0e3b783 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtConstants.java @@ -94,9 +94,19 @@ public class AdtConstants { /** Absolute path of the resource folder, e.g. "/res".<br> This is a workspace path. */ public final static String WS_RESOURCES = WS_SEP + SdkConstants.FD_RESOURCES; - /** Absolute path of the crunch cache folder, e.g. "/bin/res".<br> This is a workspace path. */ - public final static String WS_CRUNCHCACHE = WS_SEP + SdkConstants.FD_OUTPUT - + WS_SEP + SdkConstants.FD_RESOURCES; + public final static String FD_CRUNCH = "crunch"; //$NON-NLS-1$ + public final static String FD_BC = "bc"; //$NON-NLS-1$ + + /** Path of crunch cache folder relative to the output folder.<br> This is a workspace path. */ + public final static String WS_BIN_RELATIVE_CRUNCHCACHE = SdkConstants.FD_RESOURCES + + WS_SEP + FD_CRUNCH; + + /** Path of bc output folder relative to the output folder.<br> This is a workspace path. */ + public final static String WS_BIN_RELATIVE_BC = SdkConstants.FD_RESOURCES + + WS_SEP + FD_BC; + + /** Path of rs libs output folder relative to the output folder.<br> This is a workspace path. */ + public final static String WS_BIN_RELATIVE_RS_LIBS = SdkConstants.FD_RS_LIBS; /** Absolute path of the resource folder, e.g. "/assets".<br> This is a workspace path. */ public final static String WS_ASSETS = WS_SEP + SdkConstants.FD_ASSETS; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java index c5d95af..cbeb274 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java @@ -51,6 +51,7 @@ import com.android.io.StreamException; import com.android.resources.ResourceFolderType; import com.android.sdklib.IAndroidTarget; import com.android.utils.ILogger; +import com.google.common.collect.Sets; import com.google.common.io.Closeables; import org.eclipse.core.commands.Command; @@ -123,6 +124,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Set; /** * The activator class controls the plug-in life cycle @@ -153,8 +155,7 @@ public class AdtPlugin extends AbstractUIPlugin implements ILogger { private LoadStatus mSdkLoadedStatus = LoadStatus.LOADING; /** Project to update once the SDK is loaded. * Any access MUST be in a synchronized(mPostLoadProjectsToResolve) block */ - private final ArrayList<IJavaProject> mPostLoadProjectsToResolve = - new ArrayList<IJavaProject>(); + private final Set<IJavaProject> mPostLoadProjectsToResolve = Sets.newHashSet(); /** Project to check validity of cache vs actual once the SDK is loaded. * Any access MUST be in a synchronized(mPostLoadProjectsToResolve) block */ private final ArrayList<IJavaProject> mPostLoadProjectsToCheck = new ArrayList<IJavaProject>(); 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 4aeb2cc..45e350d 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 @@ -51,7 +51,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(22, 0, 0, 0); + private final static FullRevision MIN_TOOLS_REV = new FullRevision(22, 2, 1, 0); /** * 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/AaptQuickFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java index 98a1fab..3db3808 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java @@ -20,7 +20,7 @@ import static com.android.SdkConstants.ANDROID_URI; import static com.android.SdkConstants.XMLNS_ANDROID; import static com.android.SdkConstants.XMLNS_URI; -import com.android.ide.common.resources.ResourceRepository; +import com.android.ide.common.resources.ResourceUrl; import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtUtils; @@ -344,9 +344,13 @@ public class AaptQuickFix implements IMarkerResolutionGenerator2, IQuickAssistPr } private void perform() { - Pair<ResourceType,String> resource = ResourceRepository.parseResource(mResource); - ResourceType type = resource.getFirst(); - String name = resource.getSecond(); + ResourceUrl resource = ResourceUrl.parse(mResource); + if (resource == null) { + return; + } + ResourceType type = resource.type; + String name = resource.name; + assert !resource.framework; String value = ""; //$NON-NLS-1$ // Try to pick a reasonable first guess. The new value will be highlighted and diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java index cda1da0..8e831b7 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java @@ -25,6 +25,7 @@ import com.android.ide.eclipse.adt.AndroidPrintStream; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity; import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; +import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.prefs.AndroidLocation.AndroidLocationException; import com.android.sdklib.BuildToolInfo; @@ -35,6 +36,7 @@ import com.android.sdklib.build.ApkBuilder.JarStatus; import com.android.sdklib.build.ApkBuilder.SigningInfo; import com.android.sdklib.build.ApkCreationException; import com.android.sdklib.build.DuplicateFileException; +import com.android.sdklib.build.RenderScriptProcessor; import com.android.sdklib.build.SealedApkException; import com.android.sdklib.internal.build.DebugKeyProvider; import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException; @@ -107,6 +109,8 @@ public class BuildHelper { private static final String COMMAND_PACKAGE = "package"; //$NON-NLS-1$ @NonNull + private final ProjectState mProjectState; + @NonNull private final IProject mProject; @NonNull private final BuildToolInfo mBuildToolInfo; @@ -144,13 +148,14 @@ public class BuildHelper { * @param verbose * @throws CoreException */ - public BuildHelper(@NonNull IProject project, + public BuildHelper(@NonNull ProjectState projectState, @NonNull BuildToolInfo buildToolInfo, @NonNull AndroidPrintStream outStream, @NonNull AndroidPrintStream errStream, boolean forceJumbo, boolean disableDexMerger, boolean debugMode, boolean verbose, ResourceMarker resMarker) throws CoreException { - mProject = project; + mProjectState = projectState; + mProject = projectState.getProject(); mBuildToolInfo = buildToolInfo; mOutStream = outStream; mErrStream = errStream; @@ -177,7 +182,8 @@ public class BuildHelper { resPaths.add(resFolder.getLocation().toOSString()); // Get the output folder where the cache is stored. - IFolder cacheFolder = mProject.getFolder(AdtConstants.WS_CRUNCHCACHE); + IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(mProject); + IFolder cacheFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE); String cachePath = cacheFolder.getLocation().toOSString(); /* For crunching, we don't need the osManifestPath, osAssetsPath, or the configFilter @@ -219,9 +225,13 @@ public class BuildHelper { } // need to figure out some path before we can execute aapt; + IFolder binFolder = BaseProjectHelper.getAndroidOutputFolder(mProject); // get the cache folder - IFolder cacheFolder = mProject.getFolder(AdtConstants.WS_CRUNCHCACHE); + IFolder cacheFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE); + + // get the BC folder + IFolder bcFolder = binFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC); // get the resource folder IFolder resFolder = mProject.getFolder(AdtConstants.WS_RESOURCES); @@ -244,6 +254,7 @@ public class BuildHelper { // png cache folder first. addFolderToList(osResPaths, cacheFolder); + addFolderToList(osResPaths, bcFolder); // regular res folder next. osResPaths.add(resLocation.toOSString()); @@ -252,9 +263,14 @@ public class BuildHelper { if (libProjects != null) { for (IProject lib : libProjects) { // png cache folder first - IFolder libCacheFolder = lib.getFolder(AdtConstants.WS_CRUNCHCACHE); + IFolder libBinFolder = BaseProjectHelper.getAndroidOutputFolder(lib); + + IFolder libCacheFolder = libBinFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_CRUNCHCACHE); addFolderToList(osResPaths, libCacheFolder); + IFolder libBcFolder = libBinFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC); + addFolderToList(osResPaths, libBcFolder); + // regular res folder next. IFolder libResFolder = lib.getFolder(AdtConstants.WS_RESOURCES); addFolderToList(osResPaths, libResFolder); @@ -452,6 +468,23 @@ public class BuildHelper { apkBuilder.addNativeLibraries(libFolder.getLocation().toFile()); } + // next the native libraries for the renderscript support mode. + if (mProjectState.getRenderScriptSupportMode()) { + IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(mProject); + IResource rsLibFolder = androidOutputFolder.getFolder( + AdtConstants.WS_BIN_RELATIVE_RS_LIBS); + File rsLibFolderFile = rsLibFolder.getLocation().toFile(); + if (rsLibFolderFile.isDirectory()) { + apkBuilder.addNativeLibraries(rsLibFolderFile); + } + + File rsLibs = RenderScriptProcessor.getSupportNativeLibFolder( + mBuildToolInfo.getLocation().getAbsolutePath()); + if (rsLibs.isDirectory()) { + apkBuilder.addNativeLibraries(rsLibs); + } + } + // write the native libraries for the library projects. if (libProjects != null) { for (IProject lib : libProjects) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DefaultSourceChangeHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DefaultSourceChangeHandler.java new file mode 100644 index 0000000..ea0d695 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/DefaultSourceChangeHandler.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011 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.build; + +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResourceDelta; + +import java.util.HashSet; +import java.util.Set; + +/** + * Base source change handler for the {@link SourceProcessor} classes. + * + * It can be used as is, as long as the matching {@link SourceProcessor} properly implements + * its abstract methods, and the processor does not output resource files, + * or can be extended to provide custom implementation for: + * {@link #handleSourceFile(IFile, int)} + * {@link #handleGeneratedFile(IFile, int)} + * {@link #handleResourceFile(IFile, int)} + * {@link #filterResourceFolder(IContainer)} + * + */ +public class DefaultSourceChangeHandler implements SourceChangeHandler { + + private SourceProcessor mProcessor; + + /** List of source files found that are modified or new. */ + private final Set<IFile> mToCompile = new HashSet<IFile>(); + + /** List of source files that have been removed. */ + private final Set<IFile> mRemoved = new HashSet<IFile>(); + + @Override + public boolean handleGeneratedFile(IFile file, int kind) { + if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.CHANGED) { + IFile sourceFile = mProcessor.isOutput(file); + if (sourceFile != null) { + mToCompile.add(sourceFile); + return true; + } + } + + return false; + } + + @Override + public void handleSourceFile(IFile file, int kind) { + // first the file itself if this is a match for the processor's extension + if (mProcessor.getExtensions().contains(file.getFileExtension())) { + if (kind == IResourceDelta.REMOVED) { + mRemoved.add(file); + } else { + mToCompile.add(file); + } + } + + // now the dependencies. In all case we compile the files that depend on the + // added/changed/removed file. + mToCompile.addAll(mProcessor.isDependency(file)); + } + + protected void addFileToCompile(IFile file) { + mToCompile.add(file); + } + + Set<IFile> getFilesToCompile() { + return mToCompile; + } + + protected void addRemovedFile(IFile file) { + mRemoved.add(file); + } + + Set<IFile> getRemovedFiles() { + return mRemoved; + } + + public void reset() { + mToCompile.clear(); + mRemoved.clear(); + } + + protected SourceProcessor getProcessor() { + return mProcessor; + } + + void init(SourceProcessor processor) { + mProcessor = processor; + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java new file mode 100644 index 0000000..1d3c7bd --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptLauncher.java @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2011 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.build; + +import com.android.annotations.NonNull; +import com.android.ide.eclipse.adt.AdtConstants; +import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; +import com.android.sdklib.build.RenderScriptProcessor.CommandLineLauncher; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Path; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A {@link SourceProcessor} for RenderScript files. + */ +public class RenderScriptLauncher implements CommandLineLauncher { + + /** + * Single line llvm-rs-cc error: {@code <path>:<line>:<col>: <error>} + */ + private static Pattern sLlvmPattern1 = Pattern.compile("^(.+?):(\\d+):(\\d+):\\s(.+)$"); //$NON-NLS-1$ + + @NonNull + private final IProject mProject; + @NonNull + private final IFolder mSourceOutFolder; + @NonNull + private final IFolder mResOutFolder; + @NonNull + private final IProgressMonitor mMonitor; + private final boolean mVerbose; + + public RenderScriptLauncher( + @NonNull IProject project, + @NonNull IFolder sourceOutFolder, + @NonNull IFolder resOutFolder, + @NonNull IProgressMonitor monitor, + boolean verbose) { + mProject = project; + mSourceOutFolder = sourceOutFolder; + mResOutFolder = resOutFolder; + mMonitor = monitor; + mVerbose = verbose; + } + + @Override + public void launch(File executable, List<String> arguments, Map<String, String> envVariableMap) + throws IOException, InterruptedException { + // do the exec + try { + if (mVerbose) { + StringBuilder sb = new StringBuilder(executable.getAbsolutePath()); + for (String c : arguments) { + sb.append(' ').append(c); + } + String cmd_line = sb.toString(); + AdtPlugin.printToConsole(mProject, cmd_line); + } + + String[] commandArray = new String[1 + arguments.size()]; + commandArray[0] = executable.getAbsolutePath(); + System.arraycopy(arguments.toArray(), 0, commandArray, 1, arguments.size()); + + ProcessBuilder processBuilder = new ProcessBuilder(commandArray); + Map<String, String> processEnvs = processBuilder.environment(); + for (Map.Entry<String, String> entry : envVariableMap.entrySet()) { + processEnvs.put(entry.getKey(), entry.getValue()); + } + + Process p = processBuilder.start(); + + // list to store each line of stderr + ArrayList<String> stdErr = new ArrayList<String>(); + + // get the output and return code from the process + int returnCode = BuildHelper.grabProcessOutput(mProject, p, stdErr); + + if (stdErr.size() > 0) { + // attempt to parse the error output + boolean parsingError = parseLlvmOutput(stdErr); + + // If the process failed and we couldn't parse the output + // we print a message, mark the project and exit + if (returnCode != 0) { + + if (parsingError || mVerbose) { + // display the message in the console. + if (parsingError) { + AdtPlugin.printErrorToConsole(mProject, stdErr.toArray()); + + // mark the project + BaseProjectHelper.markResource(mProject, + AdtConstants.MARKER_RENDERSCRIPT, + "Unparsed Renderscript error! Check the console for output.", + IMarker.SEVERITY_ERROR); + } else { + AdtPlugin.printToConsole(mProject, stdErr.toArray()); + } + } + return; + } + } else if (returnCode != 0) { + // no stderr output but exec failed. + String msg = String.format("Error executing Renderscript: Return code %1$d", + returnCode); + + BaseProjectHelper.markResource(mProject, AdtConstants.MARKER_AIDL, + msg, IMarker.SEVERITY_ERROR); + + return; + } + } catch (IOException e) { + // mark the project and exit + String msg = String.format( + "Error executing Renderscript. Please check %1$s is present at %2$s", + executable.getName(), executable.getAbsolutePath()); + AdtPlugin.log(IStatus.ERROR, msg); + BaseProjectHelper.markResource(mProject, AdtConstants.MARKER_RENDERSCRIPT, msg, + IMarker.SEVERITY_ERROR); + throw e; + } catch (InterruptedException e) { + // mark the project and exit + String msg = String.format( + "Error executing Renderscript. Please check %1$s is present at %2$s", + executable.getName(), executable.getAbsolutePath()); + AdtPlugin.log(IStatus.ERROR, msg); + BaseProjectHelper.markResource(mProject, AdtConstants.MARKER_RENDERSCRIPT, msg, + IMarker.SEVERITY_ERROR); + throw e; + } + + try { + mSourceOutFolder.refreshLocal(IResource.DEPTH_ONE, mMonitor); + mResOutFolder.refreshLocal(IResource.DEPTH_ONE, mMonitor); + } catch (CoreException e) { + AdtPlugin.log(e, "failed to refresh folders"); + } + + return; + } + + /** + * Parse the output of llvm-rs-cc and mark the file with any errors. + * @param lines The output to parse. + * @return true if the parsing failed, false if success. + */ + private boolean parseLlvmOutput(ArrayList<String> lines) { + // nothing to parse? just return false; + if (lines.size() == 0) { + return false; + } + + // get the root folder for the project as we're going to ignore everything that's + // not in the project + String rootPath = mProject.getLocation().toOSString(); + int rootPathLength = rootPath.length(); + + Matcher m; + + boolean parsing = false; + + for (int i = 0; i < lines.size(); i++) { + String p = lines.get(i); + + m = sLlvmPattern1.matcher(p); + if (m.matches()) { + // get the file path. This may, or may not be the main file being compiled. + String filePath = m.group(1); + if (filePath.startsWith(rootPath) == false) { + // looks like the error in a non-project file. Keep parsing, but + // we'll return true + parsing = true; + continue; + } + + // get the actual file. + filePath = filePath.substring(rootPathLength); + // remove starting separator since we want the path to be relative + if (filePath.startsWith(File.separator)) { + filePath = filePath.substring(1); + } + + // get the file + IFile f = mProject.getFile(new Path(filePath)); + + String lineStr = m.group(2); + // ignore group 3 for now, this is the col number + String msg = m.group(4); + + // get the line number + int line = 0; + try { + line = Integer.parseInt(lineStr); + } catch (NumberFormatException e) { + // looks like the string we extracted wasn't a valid + // file number. Parsing failed and we return true + return true; + } + + // mark the file + BaseProjectHelper.markResource(f, AdtConstants.MARKER_RENDERSCRIPT, msg, line, + IMarker.SEVERITY_ERROR); + + // success, go to the next line + continue; + } + + // invalid line format, flag as error, and keep going + parsing = true; + } + + return parsing; + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java deleted file mode 100644 index 806e4e2..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RenderScriptProcessor.java +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (C) 2011 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.build; - -import com.android.SdkConstants; -import com.android.annotations.NonNull; -import com.android.ide.eclipse.adt.AdtConstants; -import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; -import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity; -import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; -import com.android.resources.ResourceFolderType; -import com.android.sdklib.BuildToolInfo; -import com.android.sdklib.IAndroidTarget; -import com.google.common.collect.Sets; - -import org.eclipse.core.resources.IContainer; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceDelta; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.Path; -import org.eclipse.jdt.core.IJavaProject; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * A {@link SourceProcessor} for RenderScript files. - * - */ -public class RenderScriptProcessor extends SourceProcessor { - - private static final String PROPERTY_COMPILE_RS = "compileRenderScript"; //$NON-NLS-1$ - - /** - * Single line llvm-rs-cc error: {@code <path>:<line>:<col>: <error>} - */ - private static Pattern sLlvmPattern1 = Pattern.compile("^(.+?):(\\d+):(\\d+):\\s(.+)$"); //$NON-NLS-1$ - - private final static Set<String> EXTENSIONS = Sets.newHashSetWithExpectedSize(2); - static { - EXTENSIONS.add(SdkConstants.EXT_RS); - EXTENSIONS.add(SdkConstants.EXT_FS); - } - - private static class RsChangeHandler extends SourceChangeHandler { - - @Override - public boolean handleGeneratedFile(IFile file, int kind) { - boolean r = super.handleGeneratedFile(file, kind); - if (r == false && - kind == IResourceDelta.REMOVED && - SdkConstants.EXT_DEP.equalsIgnoreCase(file.getFileExtension())) { - // This looks to be a dependency file. - // For future-proofness let's make sure this dependency file was generated by - // this processor even if it's the only processor using them for now. - - // look for the original file. - // We know we are in the gen folder, so make a path to the dependency file - // relative to the gen folder. Convert this into a Renderscript source file, - // and look to see if this file exists. - SourceProcessor processor = getProcessor(); - IFolder genFolder = processor.getGenFolder(); - IPath relative = file.getFullPath().makeRelativeTo(genFolder.getFullPath()); - // remove the file name segment - relative = relative.removeLastSegments(1); - // add the file name of a Renderscript file. - relative = relative.append(file.getName().replaceAll( - AdtConstants.RE_DEP_EXT, SdkConstants.DOT_RS)); - - if (!findInSourceFolders(processor, genFolder, relative)) { - // could be a FilterScript file? - relative = file.getFullPath().makeRelativeTo(genFolder.getFullPath()); - // remove the file name segment - relative = relative.removeLastSegments(1); - // add the file name of a FilterScript file. - relative = relative.append(file.getName().replaceAll( - AdtConstants.RE_DEP_EXT, SdkConstants.DOT_FS)); - - return findInSourceFolders(processor, genFolder, relative); - } - - return true; - } - - return r; - } - - private boolean findInSourceFolders(SourceProcessor processor, IFolder genFolder, - IPath relative) { - // now look for a match in the source folders. - List<IPath> sourceFolders = BaseProjectHelper.getSourceClasspaths( - processor.getJavaProject()); - IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); - - for (IPath sourceFolderPath : sourceFolders) { - IFolder sourceFolder = root.getFolder(sourceFolderPath); - // we don't look in the 'gen' source folder as there will be no source in there. - if (sourceFolder.exists() && sourceFolder.equals(genFolder) == false) { - IFile sourceFile = sourceFolder.getFile(relative); - SourceFileData data = processor.getFileData(sourceFile); - if (data != null) { - addFileToCompile(sourceFile); - return true; - } - } - } - - return false; - } - - @Override - protected boolean filterResourceFolder(IContainer folder) { - return ResourceFolderType.RAW.getName().equals(folder.getName()); - } - } - - private int mTargetApi = 11; - - public RenderScriptProcessor(@NonNull IJavaProject javaProject, - @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder) { - super(javaProject, buildToolInfo, genFolder, new RsChangeHandler()); - } - - public void setTargetApi(int targetApi) { - // make sure the target api value is good. Must be 11+ or llvm-rs-cc complains. - mTargetApi = targetApi < 11 ? 11 : targetApi; - } - - @Override - protected Set<String> getExtensions() { - return EXTENSIONS; - } - - @Override - protected String getSavePropertyName() { - return PROPERTY_COMPILE_RS; - } - - @Override - protected void doCompileFiles(List<IFile> sources, BaseBuilder builder, - IProject project, IAndroidTarget projectTarget, - List<IPath> sourceFolders, List<IFile> notCompiledOut, List<File> libraryProjectsOut, - IProgressMonitor monitor) throws CoreException { - - IFolder genFolder = getGenFolder(); - - IFolder rawFolder = project.getFolder( - new Path(SdkConstants.FD_RES).append(SdkConstants.FD_RES_RAW)); - - int depIndex; - - BuildToolInfo buildToolInfo = getBuildToolInfo(); - - // create the command line - String[] command = new String[15]; - int index = 0; - command[index++] = buildToolInfo.getPath(BuildToolInfo.PathId.LLVM_RS_CC); - command[index++] = "-I"; //$NON-NLS-1$ - command[index++] = buildToolInfo.getPath(BuildToolInfo.PathId.ANDROID_RS_CLANG); - command[index++] = "-I"; //$NON-NLS-1$ - command[index++] = buildToolInfo.getPath(BuildToolInfo.PathId.ANDROID_RS); - command[index++] = "-p"; //$NON-NLS-1$ - command[index++] = genFolder.getLocation().toOSString(); - command[index++] = "-o"; //$NON-NLS-1$ - command[index++] = rawFolder.getLocation().toOSString(); - - command[index++] = "-target-api"; //$NON-NLS-1$ - command[index++] = Integer.toString(mTargetApi); - - command[index++] = "-d"; //$NON-NLS-1$ - command[depIndex = index++] = null; - command[index++] = "-MD"; //$NON-NLS-1$ - - boolean verbose = AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE; - boolean someSuccess = false; - - // remove the generic marker from the project - builder.removeMarkersFromResource(project, AdtConstants.MARKER_RENDERSCRIPT); - - // loop until we've compile them all - for (IFile sourceFile : sources) { - if (verbose) { - String name = sourceFile.getName(); - IPath sourceFolderPath = getSourceFolderFor(sourceFile); - if (sourceFolderPath != null) { - // make a path to the source file relative to the source folder. - IPath relative = sourceFile.getFullPath().makeRelativeTo(sourceFolderPath); - name = relative.toString(); - } - AdtPlugin.printToConsole(project, "RenderScript: " + name); - } - - // Remove the RS error markers from the source file and the dependencies - builder.removeMarkersFromResource(sourceFile, AdtConstants.MARKER_RENDERSCRIPT); - SourceFileData data = getFileData(sourceFile); - if (data != null) { - for (IFile dep : data.getDependencyFiles()) { - builder.removeMarkersFromResource(dep, AdtConstants.MARKER_RENDERSCRIPT); - } - } - - // get the path of the source file. - IPath sourcePath = sourceFile.getLocation(); - String osSourcePath = sourcePath.toOSString(); - - // finish to set the command line. - command[depIndex] = quote(getDependencyFolder(sourceFile).getLocation().toOSString()); - command[index] = quote(osSourcePath); - - // launch the process - if (!execLlvmRsCc(builder, project, command, sourceFile, buildToolInfo.getLocation(), - verbose)) { - // llvm-rs-cc failed. File should be marked. We add the file to the list - // of file that will need compilation again. - notCompiledOut.add(sourceFile); - } else { - // Success. we'll return that we generated code and resources. - setCompilationStatus(COMPILE_STATUS_CODE | COMPILE_STATUS_RES); - - // need to parse the .d file to figure out the dependencies and the generated file - parseDependencyFileFor(sourceFile); - someSuccess = true; - } - } - - if (someSuccess) { - rawFolder.refreshLocal(IResource.DEPTH_ONE, monitor); - } - } - - private boolean execLlvmRsCc(BaseBuilder builder, IProject project, String[] command, - IFile sourceFile, File buildToolRoot, boolean verbose) { - // do the exec - try { - if (verbose) { - StringBuilder sb = new StringBuilder(); - for (String c : command) { - sb.append(c); - sb.append(' '); - } - String cmd_line = sb.toString(); - AdtPlugin.printToConsole(project, cmd_line); - } - - ProcessBuilder processBuilder = new ProcessBuilder(command); - Map<String, String> env = processBuilder.environment(); - if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_DARWIN) { - env.put("DYLD_LIBRARY_PATH", buildToolRoot.getAbsolutePath()); - } else if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_LINUX) { - env.put("LD_LIBRARY_PATH", buildToolRoot.getAbsolutePath()); - } - - Process p = processBuilder.start(); - - // list to store each line of stderr - ArrayList<String> stdErr = new ArrayList<String>(); - - // get the output and return code from the process - int returnCode = BuildHelper.grabProcessOutput(project, p, stdErr); - - if (stdErr.size() > 0) { - // attempt to parse the error output - boolean parsingError = parseLlvmOutput(stdErr); - - // If the process failed and we couldn't parse the output - // we print a message, mark the project and exit - if (returnCode != 0) { - - if (parsingError || verbose) { - // display the message in the console. - if (parsingError) { - AdtPlugin.printErrorToConsole(project, stdErr.toArray()); - - // mark the project - BaseProjectHelper.markResource(project, - AdtConstants.MARKER_RENDERSCRIPT, - "Unparsed Renderscript error! Check the console for output.", - IMarker.SEVERITY_ERROR); - } else { - AdtPlugin.printToConsole(project, stdErr.toArray()); - } - } - return false; - } - } else if (returnCode != 0) { - // no stderr output but exec failed. - String msg = String.format("Error executing Renderscript: Return code %1$d", - returnCode); - - BaseProjectHelper.markResource(project, AdtConstants.MARKER_AIDL, - msg, IMarker.SEVERITY_ERROR); - - return false; - } - } catch (IOException e) { - // mark the project and exit - String msg = String.format( - "Error executing Renderscript. Please check llvm-rs-cc is present at %1$s", - command[0]); - BaseProjectHelper.markResource(project, AdtConstants.MARKER_RENDERSCRIPT, msg, - IMarker.SEVERITY_ERROR); - return false; - } catch (InterruptedException e) { - // mark the project and exit - String msg = String.format( - "Error executing Renderscript. Please check llvm-rs-cc is present at %1$s", - command[0]); - BaseProjectHelper.markResource(project, AdtConstants.MARKER_RENDERSCRIPT, msg, - IMarker.SEVERITY_ERROR); - return false; - } - - return true; - } - - /** - * Parse the output of llvm-rs-cc and mark the file with any errors. - * @param lines The output to parse. - * @return true if the parsing failed, false if success. - */ - private boolean parseLlvmOutput(ArrayList<String> lines) { - // nothing to parse? just return false; - if (lines.size() == 0) { - return false; - } - - // get the root folder for the project as we're going to ignore everything that's - // not in the project - IProject project = getJavaProject().getProject(); - String rootPath = project.getLocation().toOSString(); - int rootPathLength = rootPath.length(); - - Matcher m; - - boolean parsing = false; - - for (int i = 0; i < lines.size(); i++) { - String p = lines.get(i); - - m = sLlvmPattern1.matcher(p); - if (m.matches()) { - // get the file path. This may, or may not be the main file being compiled. - String filePath = m.group(1); - if (filePath.startsWith(rootPath) == false) { - // looks like the error in a non-project file. Keep parsing, but - // we'll return true - parsing = true; - continue; - } - - // get the actual file. - filePath = filePath.substring(rootPathLength); - // remove starting separator since we want the path to be relative - if (filePath.startsWith(File.separator)) { - filePath = filePath.substring(1); - } - - // get the file - IFile f = project.getFile(new Path(filePath)); - - String lineStr = m.group(2); - // ignore group 3 for now, this is the col number - String msg = m.group(4); - - // get the line number - int line = 0; - try { - line = Integer.parseInt(lineStr); - } catch (NumberFormatException e) { - // looks like the string we extracted wasn't a valid - // file number. Parsing failed and we return true - return true; - } - - // mark the file - BaseProjectHelper.markResource(f, AdtConstants.MARKER_RENDERSCRIPT, msg, line, - IMarker.SEVERITY_ERROR); - - // success, go to the next line - continue; - } - - // invalid line format, flag as error, and keep going - parsing = true; - } - - return parsing; - } - - - @Override - protected void doRemoveFiles(SourceFileData bundle) throws CoreException { - // call the super implementation, it will remove the output files - super.doRemoveFiles(bundle); - - // now remove the dependency file. - IFile depFile = getDependencyFileFor(bundle.getSourceFile()); - if (depFile.exists()) { - depFile.getLocation().toFile().delete(); - } - } - - @Override - protected void loadOutputAndDependencies() { - Collection<SourceFileData> dataList = getAllFileData(); - for (SourceFileData data : dataList) { - // parse the dependency file. If this fails, force compilation of the file. - if (parseDependencyFileFor(data.getSourceFile()) == false) { - addFileToCompile(data.getSourceFile()); - } - } - } - - private boolean parseDependencyFileFor(IFile sourceFile) { - IFile depFile = getDependencyFileFor(sourceFile); - File f = depFile.getLocation().toFile(); - if (f.exists()) { - SourceFileData data = getFileData(sourceFile); - if (data == null) { - data = new SourceFileData(sourceFile); - addData(data); - } - parseDependencyFile(data, f); - return true; - } - - return false; - } - - private IFolder getDependencyFolder(IFile sourceFile) { - IPath sourceFolderPath = getSourceFolderFor(sourceFile); - - // this really shouldn't happen since the sourceFile must be in a source folder - // since it comes from the delta visitor - if (sourceFolderPath != null) { - // make a path to the source file relative to the source folder. - IPath relative = sourceFile.getFullPath().makeRelativeTo(sourceFolderPath); - // remove the file name. This is now the destination folder. - relative = relative.removeLastSegments(1); - - return getGenFolder().getFolder(relative); - } - - return null; - } - - private IFile getDependencyFileFor(IFile sourceFile) { - IFolder depFolder = getDependencyFolder(sourceFile); - return depFolder.getFile(sourceFile.getName().replaceAll(AdtConstants.RE_RS_EXT, - SdkConstants.DOT_DEP)); - } - - /** - * Parses the given dependency file and fills the given {@link SourceFileData} with it. - * - * @param data the bundle to fill. - * @param file the dependency file - */ - private void parseDependencyFile(SourceFileData data, File dependencyFile) { - //contents = file.getContents(); - String content = AdtPlugin.readFile(dependencyFile); - - // we're going to be pretty brutal here. - // The format is something like: - // output1 output2 [...]: dep1 dep2 [...] - // expect it's likely split on several lines. So let's move it back on a single line - // first - String[] lines = content.split("\n"); //$NON-NLS-1$ - StringBuilder sb = new StringBuilder(); - for (String line : lines) { - line = line.trim(); - if (line.endsWith("\\")) { //$NON-NLS-1$ - line = line.substring(0, line.length() - 1); - } - - sb.append(line); - } - - // split the left and right part - String[] files = sb.toString().split(":"); //$NON-NLS-1$ - - // get the output files: - String[] outputs = files[0].trim().split(" "); //$NON-NLS-1$ - - // and the dependency files: - String[] dependencies = files[1].trim().split(" "); //$NON-NLS-1$ - - List<IFile> outputFiles = new ArrayList<IFile>(); - List<IFile> dependencyFiles = new ArrayList<IFile>(); - - fillList(outputs, outputFiles); - fillList(dependencies, dependencyFiles); - - data.setOutputFiles(outputFiles); - data.setDependencyFiles(dependencyFiles); - } - - private void fillList(String[] paths, List<IFile> list) { - // get the root folder for the project as we're going to ignore everything that's - // not in the project - IProject project = getJavaProject().getProject(); - String rootPath = project.getLocation().toOSString(); - int rootPathLength = rootPath.length(); - - // all those should really be in the project - for (String p : paths) { - - if (p.startsWith(rootPath)) { - p = p.substring(rootPathLength); - // remove starting separator since we want the path to be relative - if (p.startsWith(File.separator)) { - p = p.substring(1); - } - - // get the file - IFile f = project.getFile(new Path(p)); - list.add(f); - } - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RsSourceChangeHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RsSourceChangeHandler.java new file mode 100644 index 0000000..715895a --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/RsSourceChangeHandler.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2013 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.build; + +import com.android.SdkConstants; +import com.android.annotations.NonNull; +import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.sdklib.build.RenderScriptChecker; + +import org.eclipse.core.resources.IFile; + +import java.io.File; +import java.io.IOException; +import java.util.Set; + +public class RsSourceChangeHandler implements SourceChangeHandler { + + private final RenderScriptChecker mChecker; + private boolean mIsCheckerLoaded = false; + + private boolean mMustCompile = false; + + public RsSourceChangeHandler(@NonNull RenderScriptChecker checker) { + mChecker = checker; + } + + @Override + public boolean handleGeneratedFile(IFile file, int kind) { + if (mMustCompile) { + return false; + } + + if (!mIsCheckerLoaded) { + try { + mChecker.loadDependencies(); + } catch (IOException e) { + // failed to load the dependency files, force a compilation, log the error. + AdtPlugin.log(e, "Failed to read dependency files"); + mMustCompile = true; + return false; + } + } + + Set<File> oldOutputs = mChecker.getOldOutputs(); + // mustCompile is always false here. + mMustCompile = oldOutputs.contains(file.getLocation().toFile()); + return mMustCompile; + } + + @Override + public void handleSourceFile(IFile file, int kind) { + if (mMustCompile) { + return; + } + + String ext = file.getFileExtension(); + if (SdkConstants.EXT_RS.equals(ext) || + SdkConstants.EXT_FS.equals(ext) || + SdkConstants.EXT_RSH.equals(ext)) { + mMustCompile = true; + } + } + + public boolean mustCompile() { + return mMustCompile; + } + + @NonNull + public RenderScriptChecker getChecker() { + return mChecker; + } + + public void prepareFullBuild() { + mMustCompile = true; + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java index 5436798..12a0551 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceChangeHandler.java @@ -16,103 +16,10 @@ package com.android.ide.eclipse.adt.internal.build; -import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IResourceDelta; -import java.util.HashSet; -import java.util.Set; +public interface SourceChangeHandler { -/** - * Base source change handler for the {@link SourceProcessor} classes. - * - * It can be used as is, as long as the matching {@link SourceProcessor} properly implements - * its abstract methods, and the processor does not output resource files, - * or can be extended to provide custom implementation for: - * {@link #handleSourceFile(IFile, int)} - * {@link #handleGeneratedFile(IFile, int)} - * {@link #handleResourceFile(IFile, int)} - * {@link #filterResourceFolder(IContainer)} - * - */ -public class SourceChangeHandler { - - private SourceProcessor mProcessor; - - /** List of source files found that are modified or new. */ - private final Set<IFile> mToCompile = new HashSet<IFile>(); - - /** List of source files that have been removed. */ - private final Set<IFile> mRemoved = new HashSet<IFile>(); - - public boolean handleGeneratedFile(IFile file, int kind) { - if (kind == IResourceDelta.REMOVED || kind == IResourceDelta.CHANGED) { - IFile sourceFile = mProcessor.isOutput(file); - if (sourceFile != null) { - mToCompile.add(sourceFile); - return true; - } - } - - return false; - } - - public void handleSourceFile(IFile file, int kind) { - // first the file itself if this is a match for the processor's extension - if (mProcessor.getExtensions().contains(file.getFileExtension())) { - if (kind == IResourceDelta.REMOVED) { - mRemoved.add(file); - } else { - mToCompile.add(file); - } - } - - // now the dependencies. In all case we compile the files that depend on the - // added/changed/removed file. - mToCompile.addAll(mProcessor.isDependency(file)); - } - - public void handleResourceFile(IFile file, int kind) { - if (filterResourceFolder(file.getParent())) { - handleGeneratedFile(file, kind); - } - } - - /** - * Called to restrict {@link #handleResourceFile(IFile, int)} on selected resource folders. - * @param folder - * @return - */ - protected boolean filterResourceFolder(IContainer folder) { - return false; - } - - protected void addFileToCompile(IFile file) { - mToCompile.add(file); - } - - Set<IFile> getFilesToCompile() { - return mToCompile; - } - - protected void addRemovedFile(IFile file) { - mRemoved.add(file); - } - - Set<IFile> getRemovedFiles() { - return mRemoved; - } - - public void reset() { - mToCompile.clear(); - mRemoved.clear(); - } - - protected SourceProcessor getProcessor() { - return mProcessor; - } - - void init(SourceProcessor processor) { - mProcessor = processor; - } + boolean handleGeneratedFile(IFile file, int kind); + void handleSourceFile(IFile file, int kind); } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java index 7dd92aa..1fc3e4e 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/SourceProcessor.java @@ -63,7 +63,7 @@ public abstract class SourceProcessor { private final IJavaProject mJavaProject; private BuildToolInfo mBuildToolInfo; private final IFolder mGenFolder; - private final SourceChangeHandler mDeltaVisitor; + private final DefaultSourceChangeHandler mDeltaVisitor; /** List of source files pending compilation at the next build */ private final List<IFile> mToCompile = new ArrayList<IFile>(); @@ -89,9 +89,11 @@ public abstract class SourceProcessor { return path; } - protected SourceProcessor(@NonNull IJavaProject javaProject, - @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder, - @NonNull SourceChangeHandler deltaVisitor) { + protected SourceProcessor( + @NonNull IJavaProject javaProject, + @NonNull BuildToolInfo buildToolInfo, + @NonNull IFolder genFolder, + @NonNull DefaultSourceChangeHandler deltaVisitor) { mJavaProject = javaProject; mBuildToolInfo = buildToolInfo; mGenFolder = genFolder; @@ -117,9 +119,11 @@ public abstract class SourceProcessor { } } - protected SourceProcessor(@NonNull IJavaProject javaProject, - @NonNull BuildToolInfo buildToolInfo, @NonNull IFolder genFolder) { - this(javaProject, buildToolInfo, genFolder, new SourceChangeHandler()); + protected SourceProcessor( + @NonNull IJavaProject javaProject, + @NonNull BuildToolInfo buildToolInfo, + @NonNull IFolder genFolder) { + this(javaProject, buildToolInfo, genFolder, new DefaultSourceChangeHandler()); } public void setBuildToolInfo(BuildToolInfo buildToolInfo) { @@ -173,7 +177,7 @@ public abstract class SourceProcessor { return mFiles.values(); } - public final SourceChangeHandler getChangeHandler() { + public final DefaultSourceChangeHandler getChangeHandler() { return mDeltaVisitor; } @@ -414,7 +418,7 @@ public abstract class SourceProcessor { * delta visitor * @param visitor the delta visitor. */ - private void mergeFileModifications(SourceChangeHandler visitor) { + private void mergeFileModifications(DefaultSourceChangeHandler visitor) { Set<IFile> toRemove = visitor.getRemovedFiles(); Set<IFile> toCompile = visitor.getFilesToCompile(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java index 529dad2..9fc19a7 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/ChangedFileSetHelper.java @@ -23,6 +23,7 @@ import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IPath; import java.util.ArrayList; @@ -81,13 +82,16 @@ class ChangedFileSetHelper { * @return a ChangeFileSet */ static ChangedFileSet getResCfs(@NonNull IProject project) { + // generated res is inside the project's android output folder + String path = getRelativeAndroidOut(project); + ChangedFileSet set = new ChangedFileSet( "resources", //$NON-NLS-1$ SdkConstants.FD_RES + "/**", //$NON-NLS-1$ - SdkConstants.FD_ASSETS + "/**"); //$NON-NLS-1$ + SdkConstants.FD_ASSETS + "/**", //$NON-NLS-1$ + path + '/' + AdtConstants.WS_BIN_RELATIVE_BC + "/**"); //$NON-NLS-1$ // output file is based on the project's android output folder - String path = getRelativeAndroidOut(project); set.setOutput(path + '/' + AdtConstants.FN_RESOURCES_AP_); return set; @@ -180,14 +184,17 @@ class ChangedFileSetHelper { return set; } + private static String getRelativePath(@NonNull IProject project, @NonNull IResource resource) { + return resource.getFullPath().makeRelativeTo(project.getFullPath()).toString(); + } + private static String getRelativeAndroidOut(@NonNull IProject project) { IFolder folder = BaseProjectHelper.getAndroidOutputFolder(project); - return folder.getFullPath().makeRelativeTo(project.getFullPath()).toString(); + return getRelativePath(project, folder); } private static String getRelativeJavaCOut(@NonNull IProject project) { IFolder folder = BaseProjectHelper.getJavaOutputFolder(project); - return folder.getFullPath().makeRelativeTo(project.getFullPath()).toString(); + return getRelativePath(project, folder); } - } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java index 81fceb1..b52ede9 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PatternBasedDeltaVisitor.java @@ -90,11 +90,11 @@ class PatternBasedDeltaVisitor implements IResourceDeltaVisitor { } else if (resource.getType() == IResource.FILE) { IPath path = resource.getFullPath().makeRelativeTo(mDeltaProject.getFullPath()); + String pathStr = path.toString(); // FIXME: no need to loop through all the sets once they have all said they need something (return false below and above) for (ChangedFileSet set : mSets) { // FIXME: should ignore sets that have already returned true. - String pathStr = path.toString(); if (set.isInput(pathStr, path)) { mResults.put(set, Boolean.TRUE); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java index 093072b..8aacb44 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PostCompilerBuilder.java @@ -371,7 +371,9 @@ public class PostCompilerBuilder extends BaseBuilder { if (DEBUG_LOG) { AdtPlugin.log(IStatus.INFO, "%s running crunch!", project.getName()); } - BuildHelper helper = new BuildHelper(project, mBuildToolInfo, + BuildHelper helper = new BuildHelper( + projectState, + mBuildToolInfo, mOutStream, mErrStream, false /*jumbo mode doesn't matter here*/, false /*dex merger doesn't matter here*/, @@ -486,7 +488,9 @@ public class PostCompilerBuilder extends BaseBuilder { AdtConstants.DEX_OPTIONS_DISABLE_MERGER); Boolean dexMerger = Boolean.valueOf(dexMergerStr); - BuildHelper helper = new BuildHelper(project, mBuildToolInfo, + BuildHelper helper = new BuildHelper( + projectState, + mBuildToolInfo, mOutStream, mErrStream, jumbo.booleanValue(), dexMerger.booleanValue(), diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java index ae6b3f5..2554c79 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerBuilder.java @@ -25,7 +25,8 @@ import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.build.AaptParser; import com.android.ide.eclipse.adt.internal.build.AidlProcessor; import com.android.ide.eclipse.adt.internal.build.Messages; -import com.android.ide.eclipse.adt.internal.build.RenderScriptProcessor; +import com.android.ide.eclipse.adt.internal.build.RenderScriptLauncher; +import com.android.ide.eclipse.adt.internal.build.RsSourceChangeHandler; import com.android.ide.eclipse.adt.internal.build.SourceProcessor; import com.android.ide.eclipse.adt.internal.lint.EclipseLintClient; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; @@ -49,6 +50,8 @@ import com.android.manifmerger.MergerLog; import com.android.sdklib.AndroidVersion; import com.android.sdklib.BuildToolInfo; import com.android.sdklib.IAndroidTarget; +import com.android.sdklib.build.RenderScriptChecker; +import com.android.sdklib.build.RenderScriptProcessor; import com.android.sdklib.internal.build.BuildConfigGenerator; import com.android.sdklib.internal.build.SymbolLoader; import com.android.sdklib.internal.build.SymbolWriter; @@ -67,6 +70,8 @@ import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceDelta; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; @@ -128,8 +133,6 @@ public class PreCompilerBuilder extends BaseBuilder { * Stored persistently in the project. */ private boolean mLastBuildConfigMode; - private final List<SourceProcessor> mProcessors = new ArrayList<SourceProcessor>(2); - /** cache of the java package defined in the manifest */ private String mManifestPackage; @@ -145,7 +148,7 @@ public class PreCompilerBuilder extends BaseBuilder { private DerivedProgressMonitor mDerivedProgressMonitor; private AidlProcessor mAidlProcessor; - private RenderScriptProcessor mRenderScriptProcessor; + private RsSourceChangeHandler mRenderScriptSourceChangeHandler; /** * Progress monitor waiting the end of the process to set a persistent value @@ -253,6 +256,8 @@ public class PreCompilerBuilder extends BaseBuilder { // as only those projects have an impact on what is generated by this builder. IProject[] result = null; + IFolder resOutFolder = null; + try { assert mDerivedProgressMonitor != null; @@ -279,13 +284,16 @@ public class PreCompilerBuilder extends BaseBuilder { // Top level check to make sure the build can move forward. abortOnBadSetup(javaProject, projectState); - setupSourceProcessors(javaProject, projectState); - // now we need to get the classpath list List<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(javaProject); IFolder androidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(project); + resOutFolder = getResOutFolder(androidOutputFolder); + + setupSourceProcessors(javaProject, projectState, sourceFolderPathList, + androidOutputFolder); + PreCompilerDeltaVisitor dv = null; String javaPackage = null; String minSdkVersion = null; @@ -305,9 +313,8 @@ public class PreCompilerBuilder extends BaseBuilder { mMustCompileResources = true; mMustCreateBuildConfig = true; - for (SourceProcessor processor : mProcessors) { - processor.prepareFullBuild(project); - } + mAidlProcessor.prepareFullBuild(project); + mRenderScriptSourceChangeHandler.prepareFullBuild(); } else { AdtPlugin.printBuildToConsole(BuildVerbosity.VERBOSE, project, Messages.Start_Inc_Pre_Compiler); @@ -320,11 +327,12 @@ public class PreCompilerBuilder extends BaseBuilder { if (delta == null) { mMustCompileResources = true; - for (SourceProcessor processor : mProcessors) { - processor.prepareFullBuild(project); - } + mAidlProcessor.prepareFullBuild(project); + mRenderScriptSourceChangeHandler.prepareFullBuild(); } else { - dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList, mProcessors); + dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList, + mAidlProcessor.getChangeHandler(), + mRenderScriptSourceChangeHandler); delta.accept(dv); // Check to see if Manifest.xml, Manifest.java, or R.java have changed: @@ -363,9 +371,7 @@ public class PreCompilerBuilder extends BaseBuilder { } } // else: already processed the deltas in ResourceManager's IRawDeltaListener - for (SourceProcessor processor : mProcessors) { - processor.doneVisiting(project); - } + mAidlProcessor.doneVisiting(project); // get the java package from the visitor javaPackage = dv.getManifestPackage(); @@ -622,9 +628,8 @@ public class PreCompilerBuilder extends BaseBuilder { mMustMergeManifest = true; mMustCompileResources = true; mMustCreateBuildConfig = true; - for (SourceProcessor processor : mProcessors) { - processor.prepareFullBuild(project); - } + mAidlProcessor.prepareFullBuild(project); + mRenderScriptSourceChangeHandler.prepareFullBuild(); saveProjectBooleanProperty(PROPERTY_MERGE_MANIFEST, mMustMergeManifest); saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mMustCompileResources); @@ -661,33 +666,22 @@ public class PreCompilerBuilder extends BaseBuilder { // run the source processors int processorStatus = SourceProcessor.COMPILE_STATUS_NONE; - // get the renderscript target - int rsTarget = minSdkValue == -1 ? 11 : minSdkValue; - String rsTargetStr = projectState.getProperty(ProjectProperties.PROPERTY_RS_TARGET); - if (rsTargetStr != null) { - try { - rsTarget = Integer.parseInt(rsTargetStr); - } catch (NumberFormatException e) { - handleException(e, String.format( - "Property %s is not an integer.", - ProjectProperties.PROPERTY_RS_TARGET)); - return result; - } - } - mRenderScriptProcessor.setTargetApi(rsTarget); + try { + processorStatus |= mAidlProcessor.compileFiles(this, + project, projectTarget, sourceFolderPathList, + libProjectsOut, monitor); + } catch (Throwable t) { + handleException(t, "Failed to run aidl. Check workspace log for detail."); + return result; + } - for (SourceProcessor processor : mProcessors) { - try { - processorStatus |= processor.compileFiles(this, - project, projectTarget, sourceFolderPathList, - libProjectsOut, monitor); - } catch (Throwable t) { - handleException(t, String.format( - "Failed to run %s. Check workspace log for detail.", - processor.getClass().getName())); - return result; - } + try { + processorStatus |= compileRs(minSdkValue, projectState, androidOutputFolder, + resOutFolder, monitor); + } catch (Throwable t) { + handleException(t, "Failed to run renderscript. Check workspace log for detail."); + return result; } // if a processor created some resources file, force recompilation of the resources. @@ -710,7 +704,7 @@ public class PreCompilerBuilder extends BaseBuilder { proguardFile = androidOutputFolder.getFile(AdtConstants.FN_AAPT_PROGUARD); } - handleResources(project, javaPackage, projectTarget, manifestFile, + handleResources(project, javaPackage, projectTarget, manifestFile, resOutFolder, libProjects, isLibrary, proguardFile); } @@ -725,11 +719,18 @@ public class PreCompilerBuilder extends BaseBuilder { // refresh the 'gen' source folder. Once this is done with the custom progress // monitor to mark all new files as derived mGenFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor); + if (resOutFolder != null) { + resOutFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor); + } } return result; } + private IFolder getResOutFolder(IFolder androidOutputFolder) { + return androidOutputFolder.getFolder(AdtConstants.WS_BIN_RELATIVE_BC); + } + @Override protected void clean(IProgressMonitor monitor) throws CoreException { super.clean(monitor); @@ -805,17 +806,95 @@ public class PreCompilerBuilder extends BaseBuilder { } private void setupSourceProcessors(@NonNull IJavaProject javaProject, - @NonNull ProjectState projectState) { + @NonNull ProjectState projectState, + @NonNull List<IPath> sourceFolderPathList, + @NonNull IFolder androidOutputFolder) { if (mAidlProcessor == null) { mAidlProcessor = new AidlProcessor(javaProject, mBuildToolInfo, mGenFolder); - mRenderScriptProcessor = new RenderScriptProcessor(javaProject, mBuildToolInfo, - mGenFolder); - mProcessors.add(mAidlProcessor); - mProcessors.add(mRenderScriptProcessor); } else { mAidlProcessor.setBuildToolInfo(mBuildToolInfo); - mRenderScriptProcessor.setBuildToolInfo(mBuildToolInfo); } + + List<File> sourceFolders = Lists.newArrayListWithCapacity(sourceFolderPathList.size()); + IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); + + for (IPath path : sourceFolderPathList) { + IResource resource = root.findMember(path); + if (resource != null && resource.exists() && resource.getType() == IResource.FOLDER) { + IPath fullPath = resource.getLocation(); + if (fullPath != null) { + sourceFolders.add(fullPath.toFile()); + } + } + } + + RenderScriptChecker checker = new RenderScriptChecker(sourceFolders, + androidOutputFolder.getLocation().toFile()); + mRenderScriptSourceChangeHandler = new RsSourceChangeHandler(checker); + } + + private int compileRs(int minSdkValue, + @NonNull ProjectState projectState, + @NonNull IFolder androidOutputFolder, + @NonNull IFolder resOutFolder, + @NonNull IProgressMonitor monitor) + throws IOException, InterruptedException { + if (!mRenderScriptSourceChangeHandler.mustCompile()) { + return SourceProcessor.COMPILE_STATUS_NONE; + } + + RenderScriptChecker checker = mRenderScriptSourceChangeHandler.getChecker(); + + List<File> inputs = checker.findInputFiles(); + List<File> importFolders = checker.getSourceFolders(); + File buildFolder = androidOutputFolder.getLocation().toFile(); + + + // get the renderscript target + int rsTarget = minSdkValue == -1 ? 11 : minSdkValue; + String rsTargetStr = projectState.getProperty(ProjectProperties.PROPERTY_RS_TARGET); + if (rsTargetStr != null) { + try { + rsTarget = Integer.parseInt(rsTargetStr); + } catch (NumberFormatException e) { + handleException(e, String.format( + "Property %s is not an integer.", + ProjectProperties.PROPERTY_RS_TARGET)); + return SourceProcessor.COMPILE_STATUS_NONE; + } + } + + RenderScriptProcessor processor = new RenderScriptProcessor( + inputs, + importFolders, + buildFolder, + mGenFolder.getLocation().toFile(), + resOutFolder.getLocation().toFile(), + new File(buildFolder, SdkConstants.FD_RS_OBJ), + new File(buildFolder, SdkConstants.FD_RS_LIBS), + mBuildToolInfo, + rsTarget, + false /*debugBuild, always false for now*/, + 3, + projectState.getRenderScriptSupportMode()); + + // clean old dependency files fiest + checker.cleanDependencies(); + + // then clean old output files + processor.cleanOldOutput(checker.getOldOutputs()); + + RenderScriptLauncher launcher = new RenderScriptLauncher( + getProject(), + mGenFolder, + resOutFolder, + monitor, + AdtPrefs.getPrefs().getBuildVerbosity() == BuildVerbosity.VERBOSE /*verbose*/); + + // and run the build + processor.build(launcher); + + return SourceProcessor.COMPILE_STATUS_CODE | SourceProcessor.COMPILE_STATUS_RES; } @SuppressWarnings("deprecation") @@ -965,8 +1044,8 @@ public class PreCompilerBuilder extends BaseBuilder { * @throws AbortBuildException */ private void handleResources(IProject project, String javaPackage, IAndroidTarget projectTarget, - IFile manifest, List<IProject> libProjects, boolean isLibrary, IFile proguardFile) - throws CoreException, AbortBuildException { + IFile manifest, IFolder resOutFolder, List<IProject> libProjects, boolean isLibrary, + IFile proguardFile) throws CoreException, AbortBuildException { // get the resource folder IFolder resFolder = project.getFolder(AdtConstants.WS_RESOURCES); @@ -1025,7 +1104,10 @@ public class PreCompilerBuilder extends BaseBuilder { String proguardFilePath = proguardFile != null ? proguardFile.getLocation().toOSString(): null; - execAapt(project, projectTarget, osOutputPath, osResPath, osManifestPath, + File resOutFile = resOutFolder.getLocation().toFile(); + String resOutPath = resOutFile.isDirectory() ? resOutFile.getAbsolutePath() : null; + + execAapt(project, projectTarget, osOutputPath, resOutPath, osResPath, osManifestPath, mainPackageFolder, libResFolders, libRFiles, isLibrary, proguardFilePath); } } @@ -1050,7 +1132,7 @@ public class PreCompilerBuilder extends BaseBuilder { */ @SuppressWarnings("deprecation") private void execAapt(IProject project, IAndroidTarget projectTarget, String osOutputPath, - String osResPath, String osManifestPath, IFolder packageFolder, + String osBcOutPath, String osResPath, String osManifestPath, IFolder packageFolder, ArrayList<IFolder> libResFolders, List<Pair<File, String>> libRFiles, boolean isLibrary, String proguardFile) throws AbortBuildException { @@ -1094,6 +1176,10 @@ public class PreCompilerBuilder extends BaseBuilder { array.add(osOutputPath); array.add("-M"); //$NON-NLS-1$ array.add(osManifestPath); + if (osBcOutPath != null) { + array.add("-S"); //$NON-NLS-1$ + array.add(osBcOutPath); + } array.add("-S"); //$NON-NLS-1$ array.add(osResPath); for (IFolder libResFolder : libResFolders) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java index f868224..57316f5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/builders/PreCompilerDeltaVisitor.java @@ -22,12 +22,12 @@ import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.build.Messages; import com.android.ide.eclipse.adt.internal.build.SourceChangeHandler; -import com.android.ide.eclipse.adt.internal.build.SourceProcessor; import com.android.ide.eclipse.adt.internal.build.builders.BaseBuilder.BaseDeltaVisitor; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity; import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper; import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; import com.android.ide.eclipse.adt.io.IFileWrapper; +import com.google.common.collect.Lists; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; @@ -40,7 +40,7 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -93,22 +93,18 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta private final List<IPath> mSourceFolders; private boolean mIsGenSourceFolder = false; - private final List<SourceChangeHandler> mSourceChangeHandlers = - new ArrayList<SourceChangeHandler>(); + private final List<SourceChangeHandler> mSourceChangeHandlers = Lists.newArrayList(); private final IWorkspaceRoot mRoot; private IFolder mAndroidOutputFolder; public PreCompilerDeltaVisitor(BaseBuilder builder, List<IPath> sourceFolders, - List<SourceProcessor> processors) { + SourceChangeHandler... handlers) { super(builder); mSourceFolders = sourceFolders; mRoot = ResourcesPlugin.getWorkspace().getRoot(); - for (SourceProcessor processor : processors) { - SourceChangeHandler handler = processor.getChangeHandler(); - mSourceChangeHandlers.add(handler); - } + mSourceChangeHandlers.addAll(Arrays.asList(handlers)); mAndroidOutputFolder = BaseProjectHelper.getAndroidOutputFolder(builder.getProject()); } @@ -296,7 +292,7 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta if (outputWarning) { if (kind == IResourceDelta.REMOVED) { - // We pring an error just so that it's red, but it's just a warning really. + // We print an error just so that it's red, but it's just a warning really. String msg = String.format(Messages.s_Removed_Recreating_s, fileName); AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg); } else if (kind == IResourceDelta.CHANGED) { @@ -354,9 +350,6 @@ class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements IResourceDelta mBuilder.getProject(), message); } - for (SourceChangeHandler handler : mSourceChangeHandlers) { - handler.handleResourceFile((IFile)resource, kind); - } // If it's an XML resource, check the syntax if (SdkConstants.EXT_XML.equalsIgnoreCase(ext) && kind != IResourceDelta.REMOVED) { // check xml Validity diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java index 0e46255..1df2e4d 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java @@ -41,7 +41,6 @@ import static com.android.SdkConstants.TAG_STYLE; import static com.android.SdkConstants.TOOLS_URI; import static com.android.SdkConstants.VIEW; import static com.android.SdkConstants.VIEW_FRAGMENT; -import static com.android.ide.common.resources.ResourceRepository.parseResource; import static com.android.xml.AndroidManifest.ATTRIBUTE_NAME; import static com.android.xml.AndroidManifest.ATTRIBUTE_PACKAGE; import static com.android.xml.AndroidManifest.NODE_ACTIVITY; @@ -54,6 +53,7 @@ import com.android.annotations.VisibleForTesting; import com.android.ide.common.resources.ResourceFile; import com.android.ide.common.resources.ResourceFolder; import com.android.ide.common.resources.ResourceRepository; +import com.android.ide.common.resources.ResourceUrl; import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtUtils; @@ -162,7 +162,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.regex.Pattern; /** * Class containing hyperlink resolvers for XML and Java files to jump to associated @@ -184,10 +183,36 @@ public class Hyperlinks { // for the various inner classes that are actual hyperlink resolvers. } - /** Regular expression matching a FQCN for a view class */ + /** + * Returns whether a string represents a valid fully qualified name for a view class. + * Does not check for existence. + */ @VisibleForTesting - /* package */ static final Pattern CLASS_PATTERN = Pattern.compile( - "(([a-zA-Z_\\$][a-zA-Z0-9_\\$]*)+\\.)+[a-zA-Z_\\$][a-zA-Z0-9_\\$]*"); //$NON-NLS-1$ + static boolean isViewClassName(String name) { + int length = name.length(); + if (length < 2 || name.indexOf('.') == -1) { + return false; + } + + boolean lastWasDot = true; + for (int i = 0; i < length; i++) { + char c = name.charAt(i); + if (lastWasDot) { + if (!Character.isJavaIdentifierStart(c)) { + return false; + } + lastWasDot = false; + } else { + if (c == '.') { + lastWasDot = true; + } else if (!Character.isJavaIdentifierPart(c)) { + return false; + } + } + } + + return !lastWasDot; + } /** Determines whether the given attribute <b>name</b> is linkable */ private static boolean isAttributeNameLink(XmlContext context) { @@ -226,12 +251,9 @@ public class Hyperlinks { return !ATTR_ID.equals(attribute.getLocalName()); } - Pair<ResourceType,String> resource = parseResource(value); + ResourceUrl resource = ResourceUrl.parse(value); if (resource != null) { - ResourceType type = resource.getFirst(); - if (type != null) { - return true; - } + return true; } return false; @@ -371,7 +393,7 @@ public class Hyperlinks { // If the element looks like a fully qualified class name (e.g. it's a custom view // element) offer it as a link String tag = context.getElement().getTagName(); - return (tag.indexOf('.') != -1 && CLASS_PATTERN.matcher(tag).matches()); + return isViewClassName(tag); } /** Returns the FQCN for a class declaration at the given context */ @@ -1130,7 +1152,7 @@ public class Hyperlinks { } } - Pair<ResourceType,String> resource = parseResource(url); + ResourceUrl resource = ResourceUrl.parse(url); if (resource == null) { String androidStyle = ANDROID_STYLE_RESOURCE_PREFIX; if (url.startsWith(ANDROID_PREFIX)) { @@ -1163,18 +1185,16 @@ public class Hyperlinks { */ @Nullable public static IHyperlink[] getResourceLinks(@Nullable IRegion range, @NonNull String url, - @NonNull IProject project, @Nullable FolderConfiguration configuration) { + @Nullable IProject project, @Nullable FolderConfiguration configuration) { List<IHyperlink> links = new ArrayList<IHyperlink>(); - Pair<ResourceType,String> resource = parseResource(url); - if (resource == null || resource.getFirst() == null) { + ResourceUrl resource = ResourceUrl.parse(url); + if (resource == null) { return null; } - ResourceType type = resource.getFirst(); - String name = resource.getSecond(); - - boolean isFramework = url.startsWith(ANDROID_PREFIX) - || url.startsWith(ANDROID_THEME_PREFIX); + ResourceType type = resource.type; + String name = resource.name; + boolean isFramework = resource.framework; if (project == null) { // Local reference *within* a framework isFramework = true; @@ -1479,6 +1499,7 @@ public class Hyperlinks { } /** Returns the project applicable to this hyperlink detection */ + @Nullable private static IProject getProject() { IFile file = AdtUtils.getActiveFile(); if (file != null) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java index 74c033c..41361a5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/ProjectCallback.java @@ -30,6 +30,7 @@ import static com.android.SdkConstants.VIEW_INCLUDE; import com.android.SdkConstants; import com.android.ide.common.rendering.LayoutLibrary; +import com.android.ide.common.rendering.RenderSecurityManager; import com.android.ide.common.rendering.api.AdapterBinding; import com.android.ide.common.rendering.api.DataBindingItem; import com.android.ide.common.rendering.api.ILayoutPullParser; @@ -82,12 +83,12 @@ public final class ProjectCallback extends LegacyCallback { private final IProject mProject; private final ClassLoader mParentClassLoader; private final ProjectResources mProjectRes; + private final Object mCredential; private boolean mUsed = false; private String mNamespace; private ProjectClassLoader mLoader = null; private LayoutLog mLogger; private LayoutLibrary mLayoutLib; - private String mLayoutName; private ILayoutPullParser mLayoutEmbeddedParser; private ResourceResolver mResourceResolver; @@ -98,13 +99,15 @@ public final class ProjectCallback extends LegacyCallback { * @param layoutLib The layout library this callback is going to be invoked from * @param projectRes the {@link ProjectResources} for the project. * @param project the project. + * @param credential the sandbox credential */ public ProjectCallback(LayoutLibrary layoutLib, - ProjectResources projectRes, IProject project) { + ProjectResources projectRes, IProject project, Object credential) { mLayoutLib = layoutLib; mParentClassLoader = layoutLib.getClassLoader(); mProjectRes = projectRes; mProject = project; + mCredential = credential; } public Set<String> getMissingClasses() { @@ -161,7 +164,15 @@ public final class ProjectCallback extends LegacyCallback { try { if (mLoader == null) { - mLoader = new ProjectClassLoader(mParentClassLoader, mProject); + // Allow creating class loaders during rendering; may be prevented by the + // RenderSecurityManager + boolean token = RenderSecurityManager.enterSafeRegion(mCredential); + try { + System.setSecurityManager(null); + mLoader = new ProjectClassLoader(mParentClassLoader, mProject); + } finally { + RenderSecurityManager.exitSafeRegion(token); + } } clazz = mLoader.loadClass(className); } catch (Exception e) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/Configuration.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/Configuration.java index 8ca0c26..2260303 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/Configuration.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/Configuration.java @@ -22,6 +22,7 @@ import static com.android.SdkConstants.STYLE_RESOURCE_PREFIX; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.ide.common.rendering.LayoutLibrary; import com.android.ide.common.rendering.api.Capability; import com.android.ide.common.resources.ResourceFolder; import com.android.ide.common.resources.ResourceRepository; @@ -29,6 +30,7 @@ import com.android.ide.common.resources.configuration.DensityQualifier; import com.android.ide.common.resources.configuration.DeviceConfigHelper; import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.ide.common.resources.configuration.LanguageQualifier; +import com.android.ide.common.resources.configuration.LayoutDirectionQualifier; import com.android.ide.common.resources.configuration.NightModeQualifier; import com.android.ide.common.resources.configuration.RegionQualifier; import com.android.ide.common.resources.configuration.ScreenSizeQualifier; @@ -41,8 +43,10 @@ import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.resources.ResourceHelper; import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; 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.Sdk; import com.android.resources.Density; +import com.android.resources.LayoutDirection; import com.android.resources.NightMode; import com.android.resources.ScreenSize; import com.android.resources.UiMode; @@ -561,6 +565,28 @@ public class Configuration { Locale locale = getLocale(); mFullConfig.setLanguageQualifier(locale.language); mFullConfig.setRegionQualifier(locale.region); + if (!locale.hasLanguage()) { + // Avoid getting the layout library if the locale doesn't have any language. + mFullConfig.setLayoutDirectionQualifier( + new LayoutDirectionQualifier(LayoutDirection.LTR)); + } else { + Sdk currentSdk = Sdk.getCurrent(); + if (currentSdk != null) { + AndroidTargetData targetData = currentSdk.getTargetData(getTarget()); + if (targetData != null) { + LayoutLibrary layoutLib = targetData.getLayoutLibrary(); + if (layoutLib != null) { + if (layoutLib.isRtl(locale.toLocaleId())) { + mFullConfig.setLayoutDirectionQualifier( + new LayoutDirectionQualifier(LayoutDirection.RTL)); + } else { + mFullConfig.setLayoutDirectionQualifier( + new LayoutDirectionQualifier(LayoutDirection.LTR)); + } + } + } + } + } // Replace the UiMode with the selected one, if one is selected UiMode uiMode = getUiMode(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/Locale.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/Locale.java index 6e67c86..879efd7 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/Locale.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/Locale.java @@ -166,4 +166,16 @@ public class Locale { .addValue(region.getValue()) .toString(); } + + /** + * Returns the locale formatted as language-region. If region is not set, + * language is returned. If language is not set, empty string is returned. + */ + public String toLocaleId() { + // Return lang-reg only if both lang and reg are present. Else return + // lang. + return hasLanguage() && hasRegion() ? + language.getValue() + "-" + region.getValue() + : hasLanguage() ? language.getValue() : ""; + } } 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 051c568..327279b 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 @@ -27,9 +27,11 @@ import static com.android.SdkConstants.FD_GEN_SOURCES; import static com.android.SdkConstants.GRID_LAYOUT; import static com.android.SdkConstants.SCROLL_VIEW; import static com.android.SdkConstants.STRING_PREFIX; +import static com.android.SdkConstants.VALUE_FALSE; import static com.android.SdkConstants.VALUE_FILL_PARENT; import static com.android.SdkConstants.VALUE_MATCH_PARENT; import static com.android.SdkConstants.VALUE_WRAP_CONTENT; +import static com.android.ide.common.rendering.RenderSecurityManager.ENABLED_PROPERTY; import static com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configuration.CFG_DEVICE; import static com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configuration.CFG_DEVICE_STATE; import static com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configuration.CFG_FOLDER; @@ -45,6 +47,8 @@ import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.ide.common.layout.BaseLayoutRule; import com.android.ide.common.rendering.LayoutLibrary; +import com.android.ide.common.rendering.RenderSecurityException; +import com.android.ide.common.rendering.RenderSecurityManager; import com.android.ide.common.rendering.StaticRenderSession; import com.android.ide.common.rendering.api.Capability; import com.android.ide.common.rendering.api.LayoutLog; @@ -284,6 +288,7 @@ public class GraphicalEditorPart extends EditorPart private FlyoutControlComposite mPaletteComposite; private PropertyFactory mPropertyFactory; private boolean mRenderedOnce; + private final Object mCredential = new Object(); /** * Flags which tracks whether this editor is currently active which is set whenever @@ -1523,11 +1528,43 @@ public class GraphicalEditorPart extends EditorPart return true; } + /** + * Creates a {@link RenderService} associated with this editor + * @return the render service + */ + @NonNull + public RenderService createRenderService() { + return RenderService.create(this, mCredential); + } + + /** + * Creates a {@link RenderLogger} associated with this editor + * @param name the name of the logger + * @return the new logger + */ + @NonNull + public RenderLogger createRenderLogger(String name) { + return new RenderLogger(name, mCredential); + } + + /** + * Creates a {@link RenderService} associated with this editor + * + * @param configuration the configuration to use (and fallback to editor for the rest) + * @param resolver a resource resolver to use to look up resources + * @return the render service + */ + @NonNull + public RenderService createRenderService(Configuration configuration, + ResourceResolver resolver) { + return RenderService.create(this, configuration, resolver, mCredential); + } + private void renderWithBridge(IProject iProject, UiDocumentNode model, LayoutLibrary layoutLib) { LayoutCanvas canvas = getCanvasControl(); Set<UiElementNode> explodeNodes = canvas.getNodesToExplode(); - RenderLogger logger = new RenderLogger(mEditedFile.getName()); + RenderLogger logger = createRenderLogger(mEditedFile.getName()); RenderingMode renderingMode = RenderingMode.NORMAL; // FIXME set the rendering mode using ViewRule or something. List<UiElementNode> children = model.getUiChildren(); @@ -1536,7 +1573,7 @@ public class GraphicalEditorPart extends EditorPart renderingMode = RenderingMode.V_SCROLL; } - RenderSession session = RenderService.create(this) + RenderSession session = RenderService.create(this, mCredential) .setModel(model) .setLog(logger) .setRenderingMode(renderingMode) @@ -1649,7 +1686,8 @@ public class GraphicalEditorPart extends EditorPart ResourceManager resManager = ResourceManager.getInstance(); IProject project = getProject(); ProjectResources projectRes = resManager.getProjectResources(project); - mProjectCallback = new ProjectCallback(layoutLibrary, projectRes, project); + mProjectCallback = new ProjectCallback(layoutLibrary, projectRes, project, + mCredential); } else if (reset) { // Also clears the set of missing/broken classes prior to rendering mProjectCallback.getMissingClasses().clear(); @@ -1813,6 +1851,12 @@ public class GraphicalEditorPart extends EditorPart } Throwable throwable = throwables.get(0); + + if (throwable instanceof RenderSecurityException) { + addActionLink(mErrorLabel, ActionLinkStyleRange.LINK_DISABLE_SANDBOX, + "\nTurn off custom view rendering sandbox\n"); + } + StackTraceElement[] frames = throwable.getStackTrace(); int end = -1; boolean haveInterestingFrame = false; @@ -2002,8 +2046,10 @@ public class GraphicalEditorPart extends EditorPart IAndroidTarget target = currentSdk.getTarget(project); if (target != null) { AndroidTargetData targetData = currentSdk.getTargetData(target); - LayoutDescriptors layoutDescriptors = targetData.getLayoutDescriptors(); - return layoutDescriptors.getAllViewClassNames(); + if (targetData != null) { + LayoutDescriptors layoutDescriptors = targetData.getLayoutDescriptors(); + return layoutDescriptors.getAllViewClassNames(); + } } return Collections.emptyList(); @@ -2341,6 +2387,8 @@ public class GraphicalEditorPart extends EditorPart private static final int SET_ATTRIBUTE = 8; /** Open the given file and line number */ private static final int LINK_OPEN_LINE = 9; + /** Disable sandbox */ + private static final int LINK_DISABLE_SANDBOX = 10; /** Client data: the contents depend on the specific action */ private final Object[] mData; @@ -2467,6 +2515,19 @@ public class GraphicalEditorPart extends EditorPart }); break; } + case LINK_DISABLE_SANDBOX: { + RenderSecurityManager.sEnabled = false; + recomputeLayout(); + + MessageDialog.openInformation(AdtPlugin.getShell(), + "Disabled Rendering Sandbox", + "The custom view rendering sandbox was disabled for this session.\n\n" + + "You can turn it off permanently by adding\n" + + "-D" + ENABLED_PROPERTY + "=" + VALUE_FALSE + "\n" + + "as a new line in eclipse.ini."); + + break; + } default: assert false : mAction; break; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PreviewIconFactory.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PreviewIconFactory.java index c92ce81..5661b29 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PreviewIconFactory.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/PreviewIconFactory.java @@ -267,7 +267,7 @@ public class PreviewIconFactory { .setModel(model) .setOverrideRenderSize(width, height) .setRenderingMode(RenderingMode.FULL_EXPAND) - .setLog(new RenderLogger("palette")) + .setLog(editor.createRenderLogger("palette")) .setOverrideBgColor(overrideBgColor) .setDecorations(false) .createRenderSession(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java index 7b9cb55..8548830 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLogger.java @@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout.gle2; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.ide.common.rendering.RenderSecurityManager; import com.android.ide.common.rendering.api.LayoutLog; import com.android.ide.eclipse.adt.AdtPlugin; @@ -43,10 +44,12 @@ public class RenderLogger extends LayoutLog { private List<String> mTags; private List<Throwable> mTraces; private static Set<String> sIgnoredFidelityWarnings; + private final Object mCredential; /** Construct a logger for the given named layout */ - RenderLogger(String name) { + RenderLogger(String name, Object credential) { mName = name; + mCredential = credential; } /** @@ -123,7 +126,7 @@ public class RenderLogger extends LayoutLog { public void error(String tag, String message, Object data) { String description = describe(message); - AdtPlugin.log(IStatus.ERROR, "%1$s: %2$s", mName, description); + appendToIdeLog(null, IStatus.ERROR, description); // Workaround: older layout libraries don't provide a tag for this error if (tag == null && message != null @@ -137,7 +140,8 @@ public class RenderLogger extends LayoutLog { @Override public void error(String tag, String message, Throwable throwable, Object data) { String description = describe(message); - AdtPlugin.log(throwable, "%1$s: %2$s", mName, description); + appendToIdeLog(throwable, IStatus.ERROR, description); + if (throwable != null) { if (throwable instanceof ClassNotFoundException) { // The project callback is given a chance to resolve classes, @@ -187,7 +191,7 @@ public class RenderLogger extends LayoutLog { } if (log) { - AdtPlugin.log(IStatus.WARNING, "%1$s: %2$s", mName, description); + appendToIdeLog(null, IStatus.WARNING, description); } addWarning(tag, description); @@ -200,7 +204,8 @@ public class RenderLogger extends LayoutLog { } String description = describe(message); - AdtPlugin.log(throwable, "%1$s: %2$s", mName, description); + appendToIdeLog(throwable, IStatus.ERROR, description); + if (throwable != null) { mHaveExceptions = true; } @@ -304,4 +309,19 @@ public class RenderLogger extends LayoutLog { return false; } } + + // Append the given message to the ADT log. Bypass the sandbox if necessary + // such that we can write to the log file. + private void appendToIdeLog(Throwable throwable, int severity, String description) { + boolean token = RenderSecurityManager.enterSafeRegion(mCredential); + try { + if (throwable != null) { + AdtPlugin.log(throwable, "%1$s: %2$s", mName, description); + } else { + AdtPlugin.log(severity, "%1$s: %2$s", mName, description); + } + } finally { + RenderSecurityManager.exitSafeRegion(token); + } + } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java index 07baaeb..5621d5f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java @@ -555,7 +555,7 @@ public class RenderPreview implements IJobChangeListener { } else { renderService.setModel(editor.getModel()); } - RenderLogger log = new RenderLogger(getDisplayName()); + RenderLogger log = editor.createRenderLogger(getDisplayName()); renderService.setLog(log); RenderSession session = renderService.createRenderSession(); Result render = session.render(1000); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderService.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderService.java index fdc5fed..c274d3c 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderService.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderService.java @@ -23,6 +23,7 @@ import com.android.ide.common.api.INode; import com.android.ide.common.api.Rect; import com.android.ide.common.rendering.HardwareConfigHelper; import com.android.ide.common.rendering.LayoutLibrary; +import com.android.ide.common.rendering.RenderSecurityManager; import com.android.ide.common.rendering.api.Capability; import com.android.ide.common.rendering.api.DrawableParams; import com.android.ide.common.rendering.api.HardwareConfig; @@ -38,11 +39,13 @@ import com.android.ide.common.rendering.api.ViewInfo; import com.android.ide.common.resources.ResourceResolver; import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.ide.eclipse.adt.AdtPlugin; +import com.android.ide.eclipse.adt.AdtUtils; import com.android.ide.eclipse.adt.internal.editors.layout.ContextPullParser; import com.android.ide.eclipse.adt.internal.editors.layout.ProjectCallback; import com.android.ide.eclipse.adt.internal.editors.layout.UiElementPullParser; import com.android.ide.eclipse.adt.internal.editors.layout.configuration.Configuration; import com.android.ide.eclipse.adt.internal.editors.layout.configuration.ConfigurationChooser; +import com.android.ide.eclipse.adt.internal.editors.layout.configuration.Locale; import com.android.ide.eclipse.adt.internal.editors.layout.gle2.IncludeFinder.Reference; import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeFactory; import com.android.ide.eclipse.adt.internal.editors.layout.gre.NodeProxy; @@ -61,6 +64,7 @@ import org.eclipse.core.resources.IProject; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; +import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -76,6 +80,8 @@ import java.util.Set; * Android layouts. This is a wrapper around the layout library. */ public class RenderService { + private static final Object RENDERING_LOCK = new Object(); + /** Reference to the file being edited. Can also be used to access the {@link IProject}. */ private final GraphicalEditorPart mEditor; @@ -90,6 +96,7 @@ public class RenderService { private final LayoutLibrary mLayoutLib; private final IImageFactory mImageFactory; private final HardwareConfigHelper mHardwareConfigHelper; + private final Locale mLocale; // The following fields are optional or configurable using the various chained // setters: @@ -101,10 +108,12 @@ public class RenderService { private Integer mOverrideBgColor; private boolean mShowDecorations = true; private Set<UiElementNode> mExpandNodes = Collections.<UiElementNode>emptySet(); + private final Object mCredential; /** Use the {@link #create} factory instead */ - private RenderService(GraphicalEditorPart editor) { + private RenderService(GraphicalEditorPart editor, Object credential) { mEditor = editor; + mCredential = credential; mProject = editor.getProject(); LayoutCanvas canvas = editor.getCanvasControl(); @@ -124,11 +133,14 @@ public class RenderService { mProjectCallback = editor.getProjectCallback(true /*reset*/, mLayoutLib); mMinSdkVersion = editor.getMinSdkVersion(); mTargetSdkVersion = editor.getTargetSdkVersion(); + mLocale = config.getLocale(); } private RenderService(GraphicalEditorPart editor, - Configuration configuration, ResourceResolver resourceResolver) { + Configuration configuration, ResourceResolver resourceResolver, + Object credential) { mEditor = editor; + mCredential = credential; mProject = editor.getProject(); LayoutCanvas canvas = editor.getCanvasControl(); @@ -146,8 +158,26 @@ public class RenderService { mProjectCallback = editor.getProjectCallback(true /*reset*/, mLayoutLib); mMinSdkVersion = editor.getMinSdkVersion(); mTargetSdkVersion = editor.getTargetSdkVersion(); + mLocale = configuration.getLocale(); } + private RenderSecurityManager createSecurityManager() { + String projectPath = null; + String sdkPath = null; + if (RenderSecurityManager.RESTRICT_READS) { + projectPath = AdtUtils.getAbsolutePath(mProject).toFile().getPath(); + Sdk sdk = Sdk.getCurrent(); + sdkPath = sdk != null ? sdk.getSdkLocation() : null; + } + RenderSecurityManager securityManager = new RenderSecurityManager(sdkPath, projectPath); + securityManager.setLogger(AdtPlugin.getDefault()); + + // Make sure this is initialized before we attempt to use it from layoutlib + Toolkit.getDefaultToolkit(); + + return securityManager; + } + /** * Returns true if this configuration supports the given rendering * capability @@ -180,9 +210,20 @@ public class RenderService { * @return a {@link RenderService} which can perform rendering services */ public static RenderService create(GraphicalEditorPart editor) { - RenderService renderService = new RenderService(editor); + // Delegate to editor such that it can pass its credential to the service + return editor.createRenderService(); + } - return renderService; + /** + * Creates a new {@link RenderService} associated with the given editor. + * + * @param editor the editor to provide configuration data such as the render target + * @param credential the sandbox credential + * @return a {@link RenderService} which can perform rendering services + */ + @NonNull + public static RenderService create(GraphicalEditorPart editor, Object credential) { + return new RenderService(editor, credential); } /** @@ -195,9 +236,22 @@ public class RenderService { */ public static RenderService create(GraphicalEditorPart editor, Configuration configuration, ResourceResolver resolver) { - RenderService renderService = new RenderService(editor, configuration, resolver); + // Delegate to editor such that it can pass its credential to the service + return editor.createRenderService(configuration, resolver); + } - return renderService; + /** + * Creates a new {@link RenderService} associated with the given editor. + * + * @param editor the editor to provide configuration data such as the render target + * @param configuration the configuration to use (and fallback to editor for the rest) + * @param resolver a resource resolver to use to look up resources + * @param credential the sandbox credential + * @return a {@link RenderService} which can perform rendering services + */ + public static RenderService create(GraphicalEditorPart editor, + Configuration configuration, ResourceResolver resolver, Object credential) { + return new RenderService(editor, configuration, resolver, credential); } /** @@ -415,10 +469,17 @@ public class RenderService { // same session params.setExtendedViewInfoMode(true); + params.setLocale(mLocale.toLocaleId()); + + ManifestInfo manifestInfo = ManifestInfo.get(mProject); + try { + params.setRtlSupport(manifestInfo.isRtlSupported()); + } catch (Exception e) { + // ignore. + } if (!mShowDecorations) { params.setForceNoDecor(); } else { - ManifestInfo manifestInfo = ManifestInfo.get(mProject); try { params.setAppLabel(manifestInfo.getApplicationLabel()); params.setAppIcon(manifestInfo.getApplicationIcon()); @@ -434,15 +495,20 @@ public class RenderService { // set the Image Overlay as the image factory. params.setImageFactory(mImageFactory); + mProjectCallback.setLogger(mLogger); + mProjectCallback.setResourceResolver(mResourceResolver); + RenderSecurityManager securityManager = createSecurityManager(); try { - mProjectCallback.setLogger(mLogger); - mProjectCallback.setResourceResolver(mResourceResolver); - return mLayoutLib.createSession(params); + securityManager.setActive(true, mCredential); + synchronized (RENDERING_LOCK) { + return mLayoutLib.createSession(params); + } } catch (RuntimeException t) { // Exceptions from the bridge mLogger.error(null, t.getLocalizedMessage(), t, null); throw t; } finally { + securityManager.dispose(mCredential); mProjectCallback.setLogger(null); mProjectCallback.setResourceResolver(null); } @@ -542,10 +608,14 @@ public class RenderService { params.setForceNoDecor(); RenderSession session = null; + mProjectCallback.setLogger(mLogger); + mProjectCallback.setResourceResolver(mResourceResolver); + RenderSecurityManager securityManager = createSecurityManager(); try { - mProjectCallback.setLogger(mLogger); - mProjectCallback.setResourceResolver(mResourceResolver); - session = mLayoutLib.createSession(params); + securityManager.setActive(true, mCredential); + synchronized (RENDERING_LOCK) { + session = mLayoutLib.createSession(params); + } if (session.getResult().isSuccess()) { assert session.getRootViews().size() == 1; ViewInfo root = session.getRootViews().get(0); @@ -568,6 +638,7 @@ public class RenderService { mLogger.error(null, t.getLocalizedMessage(), t, null); throw t; } finally { + securityManager.dispose(mCredential); mProjectCallback.setLogger(null); mProjectCallback.setResourceResolver(null); if (session != null) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringAssistant.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringAssistant.java index 88423e4..aa8c119 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringAssistant.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/refactoring/RefactoringAssistant.java @@ -16,6 +16,7 @@ package com.android.ide.eclipse.adt.internal.editors.layout.refactoring; +import com.android.ide.common.resources.ResourceUrl; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor; import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditorDelegate; @@ -26,7 +27,6 @@ import com.android.ide.eclipse.adt.internal.refactorings.core.RenameResourceXmlT import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring; import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard; import com.android.resources.ResourceType; -import com.android.utils.Pair; import org.eclipse.core.resources.IFile; import org.eclipse.jface.text.IDocument; @@ -106,7 +106,7 @@ public class RefactoringAssistant implements IQuickAssistProcessor { boolean isTagName = false; boolean isAttributeName = false; boolean isStylableAttribute = false; - Pair<ResourceType, String> resource = null; + ResourceUrl resource = null; IStructuredModel model = null; try { model = xmlEditor.getModelForRead(); @@ -185,8 +185,7 @@ public class RefactoringAssistant implements IQuickAssistProcessor { new ExtractStringRefactoring(file, xmlEditor, textSelection))); } else if (resource != null) { RenameResourceProcessor processor = new RenameResourceProcessor( - file.getProject(), resource.getFirst(), - resource.getSecond(), null); + file.getProject(), resource.type, resource.name, null); RenameRefactoring refactoring = new RenameRefactoring(processor); proposals.add(new RefactoringProposal(xmlEditor, refactoring)); } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java index e43b04c..9b26057 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/manifest/ManifestInfo.java @@ -24,12 +24,14 @@ import static com.android.xml.AndroidManifest.ATTRIBUTE_LABEL; import static com.android.xml.AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION; import static com.android.xml.AndroidManifest.ATTRIBUTE_NAME; import static com.android.xml.AndroidManifest.ATTRIBUTE_PACKAGE; +import static com.android.xml.AndroidManifest.ATTRIBUTE_SUPPORTS_RTL; import static com.android.xml.AndroidManifest.ATTRIBUTE_TARGET_SDK_VERSION; import static com.android.xml.AndroidManifest.ATTRIBUTE_THEME; import static com.android.xml.AndroidManifest.NODE_ACTIVITY; import static com.android.xml.AndroidManifest.NODE_USES_SDK; import static org.eclipse.jdt.core.search.IJavaSearchConstants.REFERENCES; +import com.android.SdkConstants; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.ide.eclipse.adt.AdtPlugin; @@ -116,6 +118,7 @@ public class ManifestInfo { private int mTargetSdk; private String mApplicationIcon; private String mApplicationLabel; + private boolean mApplicationSupportsRtl; /** * Qualified name for the per-project non-persistent property storing the @@ -206,6 +209,7 @@ public class ManifestInfo { mPackage = ""; //$NON-NLS-1$ mApplicationIcon = null; mApplicationLabel = null; + mApplicationSupportsRtl = false; Document document = null; try { @@ -243,6 +247,10 @@ public class ManifestInfo { if (application.hasAttributeNS(NS_RESOURCES, ATTRIBUTE_LABEL)) { mApplicationLabel = application.getAttributeNS(NS_RESOURCES, ATTRIBUTE_LABEL); } + if (SdkConstants.VALUE_TRUE.equals(application.getAttributeNS(NS_RESOURCES, + ATTRIBUTE_SUPPORTS_RTL))) { + mApplicationSupportsRtl = true; + } String defaultTheme = application.getAttributeNS(NS_RESOURCES, ATTRIBUTE_THEME); if (defaultTheme != null && !defaultTheme.isEmpty()) { @@ -386,6 +394,15 @@ public class ManifestInfo { } /** + * Returns true if the application has RTL support. + * + * @return true if the application has RTL support. + */ + public boolean isRtlSupported() { + sync(); + return mApplicationSupportsRtl; + } + /** * Returns the target SDK version * * @return the target SDK version diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchConfiguration.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchConfiguration.java index df30879..580bbbe 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchConfiguration.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchConfiguration.java @@ -94,6 +94,12 @@ public class AndroidLaunchConfiguration { */ public String mEmulatorCommandLine; + /** Flag indicating whether the same device should be used for future launches. */ + public boolean mReuseLastUsedDevice = false; + + /** Serial number of the device used in the last launch of this config. */ + public String mLastUsedDevice = null; + /** * Initialized the structure from an ILaunchConfiguration object. * @param config @@ -109,6 +115,15 @@ public class AndroidLaunchConfiguration { mTargetMode = parseTargetMode(config, mTargetMode); try { + mReuseLastUsedDevice = config.getAttribute( + LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, false); + mLastUsedDevice = config.getAttribute( + LaunchConfigDelegate.ATTR_LAST_USED_DEVICE, (String)null); + } catch (CoreException e) { + // nothing to be done here, we'll use the default value + } + + try { mAvdName = config.getAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, mAvdName); } catch (CoreException e) { // ignore diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java index 6818789..a95ed68 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/AndroidLaunchController.java @@ -16,6 +16,8 @@ package com.android.ide.eclipse.adt.internal.launch; +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; import com.android.ddmlib.AdbCommandRejectedException; import com.android.ddmlib.AndroidDebugBridge; import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener; @@ -361,12 +363,15 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener * the app (by api level), and launch on all the others. */ IDevice[] devices = AndroidDebugBridge.getBridge().getDevices(); - IDevice deviceUsedInLastLaunch = DeviceChoiceCache.get( - launch.getLaunchConfiguration().getName()); - if (deviceUsedInLastLaunch != null) { - response.setDeviceToUse(deviceUsedInLastLaunch); - continueLaunch(response, project, launch, launchInfo, config); - return; + if (config.mReuseLastUsedDevice) { + // check to see if the last used device is still online + IDevice lastUsedDevice = getDeviceIfOnline(config.mLastUsedDevice, + devices); + if (lastUsedDevice != null) { + response.setDeviceToUse(lastUsedDevice); + continueLaunch(response, project, launch, launchInfo, config); + return; + } } if (config.mTargetMode == TargetMode.AUTO) { @@ -524,7 +529,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener public void run() { Shell shell = display.getActiveShell(); if (MessageDialog.openQuestion(shell, "Android AVD Error", - "No compatible targets were found. Do you wish to a add new Android Virtual Device?")) { + "No compatible targets were found. Do you wish to add a new Android Virtual Device?")) { AvdManagerAction action = new AvdManagerAction(); action.run(null /*action*/); searchAgain[0] = true; @@ -611,9 +616,11 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener DeviceChooserDialog dialog = new DeviceChooserDialog( AdtPlugin.getShell(), response, launchInfo.getPackageName(), - desiredProjectTarget, minApiVersion); + desiredProjectTarget, minApiVersion, + config.mReuseLastUsedDevice); if (dialog.open() == Dialog.OK) { - DeviceChoiceCache.put(launch.getLaunchConfiguration().getName(), response); + updateLaunchConfigWithLastUsedDevice(launch.getLaunchConfiguration(), + response); continueLaunch.set(true); } else { AdtPlugin.printErrorToConsole(project, "Launch canceled!"); @@ -1807,4 +1814,59 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener mWaitingForDebuggerApplications.remove(launchInfo); } } + + public static void updateLaunchConfigWithLastUsedDevice( + ILaunchConfiguration launchConfiguration, DeviceChooserResponse response) { + try { + boolean configModified = false; + boolean reuse = launchConfiguration.getAttribute( + LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, false); + String serial = launchConfiguration.getAttribute( + LaunchConfigDelegate.ATTR_LAST_USED_DEVICE, (String)null); + + ILaunchConfigurationWorkingCopy wc = launchConfiguration.getWorkingCopy(); + if (reuse != response.useDeviceForFutureLaunches()) { + reuse = response.useDeviceForFutureLaunches(); + wc.setAttribute(LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, reuse); + configModified = true; + } + + if (reuse) { + String selected = getSerial(response); + if (selected != null && !selected.equalsIgnoreCase(serial)) { + wc.setAttribute(LaunchConfigDelegate.ATTR_LAST_USED_DEVICE, selected); + configModified = true; + } + } + + if (configModified) { + wc.doSave(); + } + } catch (CoreException e) { + // in such a case, users just won't see this setting take effect + return; + } + } + + private static String getSerial(DeviceChooserResponse response) { + AvdInfo avd = response.getAvdToLaunch(); + return (avd != null) ? avd.getName() : response.getDeviceToUse().getSerialNumber(); + } + + @Nullable + public static IDevice getDeviceIfOnline(@Nullable String serial, + @NonNull IDevice[] onlineDevices) { + if (serial == null) { + return null; + } + + for (IDevice device : onlineDevices) { + if (serial.equals(device.getAvdName()) || + serial.equals(device.getSerialNumber())) { + return device; + } + } + + return null; + } } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChoiceCache.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChoiceCache.java deleted file mode 100644 index ecf596d..0000000 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChoiceCache.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.launch; - -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.IDevice; -import com.android.ide.eclipse.adt.internal.launch.DeviceChooserDialog.DeviceChooserResponse; -import com.android.sdklib.internal.avd.AvdInfo; - -import java.util.HashMap; -import java.util.Map; - -/** - * {@link DeviceChoiceCache} maps a launch configuration name to the device selected for use - * in that launch configuration by the {@link DeviceChooserDialog}. - */ -public class DeviceChoiceCache { - private static final Map<String, String> sDeviceUsedForLaunch = new HashMap<String, String>(); - - public static IDevice get(String launchConfigName) { - // obtain the cached entry - String deviceName = sDeviceUsedForLaunch.get(launchConfigName); - if (deviceName == null) { - return null; - } - - // verify that the device is still online - for (IDevice device : getOnlineDevices()) { - if (deviceName.equals(device.getAvdName()) || - deviceName.equals(device.getSerialNumber())) { - return device; - } - } - - // remove from cache if device is not online anymore - sDeviceUsedForLaunch.remove(launchConfigName); - - return null; - } - - public static void put(String launchConfigName, DeviceChooserResponse response) { - if (!response.useDeviceForFutureLaunches()) { - return; - } - - AvdInfo avd = response.getAvdToLaunch(); - String device = null; - if (avd != null) { - device = avd.getName(); - } else { - device = response.getDeviceToUse().getSerialNumber(); - } - - sDeviceUsedForLaunch.put(launchConfigName, device); - } - - private static IDevice[] getOnlineDevices() { - AndroidDebugBridge bridge = AndroidDebugBridge.getBridge(); - if (bridge != null) { - return bridge.getDevices(); - } else { - return new IDevice[0]; - } - } -} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java index 10dcd01..1b850c9 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/DeviceChooserDialog.java @@ -88,7 +88,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener private Button mDeviceRadioButton; private Button mUseDeviceForFutureLaunchesCheckbox; - private static boolean sUseDeviceForFutureLaunchesValue = false; + private boolean mUseDeviceForFutureLaunches; private boolean mDisableAvdSelectionChange = false; @@ -284,7 +284,8 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener } public DeviceChooserDialog(Shell parent, DeviceChooserResponse response, String packageName, - IAndroidTarget projectTarget, AndroidVersion minApiVersion) { + IAndroidTarget projectTarget, AndroidVersion minApiVersion, + boolean useDeviceForFutureLaunches) { super(parent); mResponse = response; @@ -292,6 +293,7 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener mProjectTarget = projectTarget; mMinApiVersion = minApiVersion; mSdk = Sdk.getCurrent(); + mUseDeviceForFutureLaunches = useDeviceForFutureLaunches; AndroidDebugBridge.addDeviceChangeListener(this); loadImages(); @@ -339,15 +341,15 @@ public class DeviceChooserDialog extends Dialog implements IDeviceChangeListener composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mUseDeviceForFutureLaunchesCheckbox = new Button(composite, SWT.CHECK); - mUseDeviceForFutureLaunchesCheckbox.setSelection(sUseDeviceForFutureLaunchesValue); - mResponse.setUseDeviceForFutureLaunches(sUseDeviceForFutureLaunchesValue); + mUseDeviceForFutureLaunchesCheckbox.setSelection(mUseDeviceForFutureLaunches); + mResponse.setUseDeviceForFutureLaunches(mUseDeviceForFutureLaunches); mUseDeviceForFutureLaunchesCheckbox.setText("Use same device for future launches"); mUseDeviceForFutureLaunchesCheckbox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { - sUseDeviceForFutureLaunchesValue = + mUseDeviceForFutureLaunches = mUseDeviceForFutureLaunchesCheckbox.getSelection(); - mResponse.setUseDeviceForFutureLaunches(sUseDeviceForFutureLaunchesValue); + mResponse.setUseDeviceForFutureLaunches(mUseDeviceForFutureLaunches); } }); mUseDeviceForFutureLaunchesCheckbox.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java index eee1542..248cb7a 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/EmulatorConfigTab.java @@ -84,26 +84,17 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { private Button mAutoTargetButton; private Button mManualTargetButton; - private AvdSelector mPreferredAvdSelector; - private Combo mSpeedCombo; - private Combo mDelayCombo; - private Group mEmulatorOptionsGroup; - private Text mEmulatorCLOptions; - private Button mWipeDataButton; - private Button mNoBootAnimButton; - private Label mPreferredAvdLabel; - private IAndroidTarget mProjectTarget; private AndroidVersion mProjectMinApiVersion; - + private Button mFutureLaunchesOnSameDevice; private boolean mSupportMultiDeviceLaunch; private Button mAllDevicesTargetButton; private Combo mDeviceTypeCombo; @@ -256,6 +247,10 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { mPreferredAvdSelector.setSelectionListener(listener); mDeviceTypeCombo.addSelectionListener(listener); + mFutureLaunchesOnSameDevice = new Button(targetModeGroup, SWT.CHECK); + mFutureLaunchesOnSameDevice.setText("Use same device for future launches"); + mFutureLaunchesOnSameDevice.addSelectionListener(listener); + // emulator size mEmulatorOptionsGroup = new Group(topComp, SWT.NONE); mEmulatorOptionsGroup.setText("Emulator launch parameters:"); @@ -280,13 +275,7 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { for (String[] speed : NETWORK_SPEEDS) { mSpeedCombo.add(speed[0]); } - mSpeedCombo.addSelectionListener(new SelectionAdapter() { - // called when selection changes - @Override - public void widgetSelected(SelectionEvent e) { - updateLaunchConfigurationDialog(); - } - }); + mSpeedCombo.addSelectionListener(listener); mSpeedCombo.pack(); new Label(mEmulatorOptionsGroup, SWT.NONE).setText("Network Latency:"); @@ -296,13 +285,7 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { for (String[] delay : NETWORK_LATENCIES) { mDelayCombo.add(delay[0]); } - mDelayCombo.addSelectionListener(new SelectionAdapter() { - // called when selection changes - @Override - public void widgetSelected(SelectionEvent e) { - updateLaunchConfigurationDialog(); - } - }); + mDelayCombo.addSelectionListener(listener); mDelayCombo.pack(); // wipe data option @@ -312,12 +295,7 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; mWipeDataButton.setLayoutData(gd); - mWipeDataButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - updateLaunchConfigurationDialog(); - } - }); + mWipeDataButton.addSelectionListener(listener); // no boot anim option mNoBootAnimButton = new Button(mEmulatorOptionsGroup, SWT.CHECK); @@ -326,12 +304,7 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; mNoBootAnimButton.setLayoutData(gd); - mNoBootAnimButton.addSelectionListener(new SelectionAdapter() { - @Override - public void widgetSelected(SelectionEvent e) { - updateLaunchConfigurationDialog(); - } - }); + mNoBootAnimButton.addSelectionListener(listener); // custom command line option for emulator l = new Label(mEmulatorOptionsGroup, SWT.NONE); @@ -427,6 +400,15 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { targetModeChanged(); + boolean reuseLastUsedDevice; + try { + reuseLastUsedDevice = configuration.getAttribute( + LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, false); + } catch (CoreException ex) { + reuseLastUsedDevice = false; + } + mFutureLaunchesOnSameDevice.setSelection(reuseLastUsedDevice); + mDeviceTypeCombo.setEnabled(multipleDevices); if (multipleDevices) { int index = 0; @@ -552,6 +534,8 @@ public class EmulatorConfigTab extends AbstractLaunchConfigurationTab { public void performApply(ILaunchConfigurationWorkingCopy configuration) { configuration.setAttribute(LaunchConfigDelegate.ATTR_TARGET_MODE, getCurrentTargetMode().toString()); + configuration.setAttribute(LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, + mFutureLaunchesOnSameDevice.getSelection()); AvdInfo avd = mPreferredAvdSelector.getSelected(); if (avd != null) { configuration.setAttribute(LaunchConfigDelegate.ATTR_AVD_NAME, avd.getName()); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigDelegate.java index c9e7e6a..86fc2ff 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigDelegate.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/launch/LaunchConfigDelegate.java @@ -51,6 +51,14 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate { public static final String ATTR_TARGET_MODE = AdtPlugin.PLUGIN_ID + ".target"; //$NON-NLS-1$ public static final TargetMode DEFAULT_TARGET_MODE = TargetMode.AUTO; + /** Flag indicating whether the last used device should be used for future launches. */ + public static final String ATTR_REUSE_LAST_USED_DEVICE = + AdtPlugin.PLUGIN_ID + ".reuse.last.used.device"; //$NON-NLS-1$ + + /** Device on which the last launch happened. */ + public static final String ATTR_LAST_USED_DEVICE = + AdtPlugin.PLUGIN_ID + ".last.used.device"; //$NON-NLS-1$ + /** * Launch action: * <ul> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java index c526edf..f9382c5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.java @@ -185,64 +185,71 @@ public class AndroidClasspathContainerInitializer extends BaseClasspathContainer // if we are loaded and the target is non null, we create a valid // ClassPathContainer if (sdkIsLoaded && target != null) { - // first make sure the target has loaded its data - Sdk.getCurrent().checkAndLoadTargetData(target, null /*project*/); - - String targetName = target.getClasspathName(); - - return new AndroidClasspathContainer( - createClasspathEntries(iProject, target, targetName), - new Path(AdtConstants.CONTAINER_FRAMEWORK), - targetName, - IClasspathContainer.K_DEFAULT_SYSTEM); - } - - // In case of error, we'll try different thing to provide the best error message - // possible. - // Get the project's target's hash string (if it exists) - String hashString = state.getTargetHashString(); - - if (hashString == null || hashString.length() == 0) { - // if there is no hash string we only show this if the SDK is loaded. - // For a project opened at start-up with no target, this would be displayed - // twice, once when the project is opened, and once after the SDK has - // finished loading. - // By testing the sdk is loaded, we only show this once in the console. - if (sdkIsLoaded) { - markerMessage = String.format( - "Project has no target set. Edit the project properties to set one."); + // check the renderscript support mode. If support mode is enabled, + // target API must be 18+ + if (!state.getRenderScriptSupportMode() || + target.getVersion().getApiLevel() >= 18) { + // first make sure the target has loaded its data + Sdk.getCurrent().checkAndLoadTargetData(target, null /*project*/); + + String targetName = target.getClasspathName(); + + return new AndroidClasspathContainer( + createClasspathEntries(iProject, target, targetName), + new Path(AdtConstants.CONTAINER_FRAMEWORK), + targetName, + IClasspathContainer.K_DEFAULT_SYSTEM); + } else { + markerMessage = "Renderscript support mode requires compilation target API to be 18+."; } - } else if (sdkIsLoaded) { - markerMessage = String.format( - "Unable to resolve target '%s'", hashString); } else { - // this is the case where there is a hashString but the SDK is not yet - // loaded and therefore we can't get the target yet. - // We check if there is a cache of the needed information. - AndroidClasspathContainer container = getContainerFromCache(iProject, - target); - - if (container == null) { - // either the cache was wrong (ie folder does not exists anymore), or - // there was no cache. In this case we need to make sure the project - // is resolved again after the SDK is loaded. - plugin.setProjectToResolve(javaProject); - + // In case of error, we'll try different thing to provide the best error message + // possible. + // Get the project's target's hash string (if it exists) + String hashString = state.getTargetHashString(); + + if (hashString == null || hashString.length() == 0) { + // if there is no hash string we only show this if the SDK is loaded. + // For a project opened at start-up with no target, this would be displayed + // twice, once when the project is opened, and once after the SDK has + // finished loading. + // By testing the sdk is loaded, we only show this once in the console. + if (sdkIsLoaded) { + markerMessage = String.format( + "Project has no target set. Edit the project properties to set one."); + } + } else if (sdkIsLoaded) { markerMessage = String.format( - "Unable to resolve target '%s' until the SDK is loaded.", - hashString); - - // let's not log this one to the console as it will happen at - // every boot, and it's expected. (we do keep the error marker though). - outputToConsole = false; - + "Unable to resolve target '%s'", hashString); } else { - // we created a container from the cache, so we register the project - // to be checked for cache validity once the SDK is loaded - plugin.setProjectToCheck(javaProject); - - // and return the container - return container; + // this is the case where there is a hashString but the SDK is not yet + // loaded and therefore we can't get the target yet. + // We check if there is a cache of the needed information. + AndroidClasspathContainer container = getContainerFromCache(iProject, + target); + + if (container == null) { + // either the cache was wrong (ie folder does not exists anymore), or + // there was no cache. In this case we need to make sure the project + // is resolved again after the SDK is loaded. + plugin.setProjectToResolve(javaProject); + + markerMessage = String.format( + "Unable to resolve target '%s' until the SDK is loaded.", + hashString); + + // let's not log this one to the console as it will happen at + // every boot, and it's expected. (we do keep the error marker though). + outputToConsole = false; + + } else { + // we created a container from the cache, so we register the project + // to be checked for cache validity once the SDK is loaded + plugin.setProjectToCheck(javaProject); + + // and return the container + return container; + } } } } 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 a7db983..57632ea 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 @@ -21,6 +21,7 @@ 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.google.common.collect.Lists; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IMarker; @@ -77,8 +78,9 @@ public final class BaseProjectHelper { * @param javaProject * @return a list of path relative to the workspace root. */ + @NonNull public static List<IPath> getSourceClasspaths(IJavaProject javaProject) { - ArrayList<IPath> sourceList = new ArrayList<IPath>(); + List<IPath> sourceList = Lists.newArrayList(); IClasspathEntry[] classpaths = javaProject.readRawClasspath(); if (classpaths != null) { for (IClasspathEntry e : classpaths) { @@ -87,6 +89,7 @@ public final class BaseProjectHelper { } } } + return sourceList; } @@ -507,6 +510,7 @@ public final class BaseProjectHelper { * @param project the {@link IProject} * @return an IFolder item or null. */ + @Nullable public final static IFolder getAndroidOutputFolder(IProject project) { try { if (project.isOpen() && project.hasNature(JavaCore.NATURE_ID)) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java index 52870a4..8168590 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java @@ -143,7 +143,9 @@ public final class ExportHelper { "No Build Tools installed in the SDK.")); } - BuildHelper helper = new BuildHelper(project, buildToolInfo, + BuildHelper helper = new BuildHelper( + projectState, + buildToolInfo, fakeStream, fakeStream, jumbo.booleanValue(), dexMerger.booleanValue(), diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java index 3beb181..1e0ada0 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/LibraryClasspathContainerInitializer.java @@ -19,14 +19,17 @@ package com.android.ide.eclipse.adt.internal.project; import static com.android.ide.eclipse.adt.AdtConstants.CONTAINER_DEPENDENCIES; import com.android.SdkConstants; +import com.android.ide.common.sdk.LoadStatus; import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AndroidPrintStream; import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; +import com.android.sdklib.BuildToolInfo; import com.android.sdklib.build.JarListSanitizer; import com.android.sdklib.build.JarListSanitizer.DifferentLibException; import com.android.sdklib.build.JarListSanitizer.Sha1Exception; +import com.android.sdklib.build.RenderScriptProcessor; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; @@ -306,60 +309,88 @@ public class LibraryClasspathContainerInitializer extends BaseClasspathContainer final Set<File> jarFiles = new HashSet<File>(); final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); - // check if the project has a valid target. - final ProjectState state = Sdk.getProjectState(iProject); - if (state == null) { - // getProjectState should already have logged an error. Just bail out. + AdtPlugin plugin = AdtPlugin.getDefault(); + if (plugin == null) { // This is totally weird, but I've seen it happen! return null; } - // annotations support for older version of android - if (state.getTarget() != null && state.getTarget().getVersion().getApiLevel() <= 15) { - File annotationsJar = new File(Sdk.getCurrent().getSdkLocation(), - SdkConstants.FD_TOOLS + File.separator + SdkConstants.FD_SUPPORT + - File.separator + SdkConstants.FN_ANNOTATIONS_JAR); + synchronized (Sdk.getLock()) { + boolean sdkIsLoaded = plugin.getSdkLoadStatus() == LoadStatus.LOADED; - jarFiles.add(annotationsJar); - } + // check if the project has a valid target. + final ProjectState state = Sdk.getProjectState(iProject); + if (state == null) { + // getProjectState should already have logged an error. Just bail out. + return null; + } - // process all the libraries + // annotations support for older version of android + if (state.getTarget() != null && state.getTarget().getVersion().getApiLevel() <= 15) { + File annotationsJar = new File(Sdk.getCurrent().getSdkLocation(), + SdkConstants.FD_TOOLS + File.separator + SdkConstants.FD_SUPPORT + + File.separator + SdkConstants.FN_ANNOTATIONS_JAR); - List<IProject> libProjects = state.getFullLibraryProjects(); - for (IProject libProject : libProjects) { - // get the project output - IFolder outputFolder = BaseProjectHelper.getAndroidOutputFolder(libProject); - - if (outputFolder != null) { // can happen when closing/deleting a library) - IFile jarIFile = outputFolder.getFile(libProject.getName().toLowerCase() + - SdkConstants.DOT_JAR); - - // get the source folder for the library project - List<IPath> srcs = BaseProjectHelper.getSourceClasspaths(libProject); - // find the first non-derived source folder. - IPath sourceFolder = null; - for (IPath src : srcs) { - IFolder srcFolder = workspaceRoot.getFolder(src); - if (srcFolder.isDerived() == false) { - sourceFolder = src; - break; + jarFiles.add(annotationsJar); + } + + if (state.getRenderScriptSupportMode()) { + if (!sdkIsLoaded) { + return null; + } + BuildToolInfo buildToolInfo = state.getBuildToolInfo(); + if (buildToolInfo == null) { + buildToolInfo = Sdk.getCurrent().getLatestBuildTool(); + + if (buildToolInfo == null) { + return null; } + + File renderScriptSupportJar = RenderScriptProcessor.getSupportJar( + buildToolInfo.getLocation().getAbsolutePath()); + + jarFiles.add(renderScriptSupportJar); } + } - // we can directly add a CPE for this jar as there's no risk of a duplicate. - IClasspathEntry entry = JavaCore.newLibraryEntry( - jarIFile.getLocation(), - sourceFolder, // source attachment path - null, // default source attachment root path. - true /*isExported*/); + // process all the libraries + + List<IProject> libProjects = state.getFullLibraryProjects(); + for (IProject libProject : libProjects) { + // get the project output + IFolder outputFolder = BaseProjectHelper.getAndroidOutputFolder(libProject); + + if (outputFolder != null) { // can happen when closing/deleting a library) + IFile jarIFile = outputFolder.getFile(libProject.getName().toLowerCase() + + SdkConstants.DOT_JAR); + + // get the source folder for the library project + List<IPath> srcs = BaseProjectHelper.getSourceClasspaths(libProject); + // find the first non-derived source folder. + IPath sourceFolder = null; + for (IPath src : srcs) { + IFolder srcFolder = workspaceRoot.getFolder(src); + if (srcFolder.isDerived() == false) { + sourceFolder = src; + break; + } + } - entries.add(entry); + // we can directly add a CPE for this jar as there's no risk of a duplicate. + IClasspathEntry entry = JavaCore.newLibraryEntry( + jarIFile.getLocation(), + sourceFolder, // source attachment path + null, // default source attachment root path. + true /*isExported*/); + + entries.add(entry); + } } - } - entries.addAll(convertJarsToClasspathEntries(iProject, jarFiles)); + entries.addAll(convertJarsToClasspathEntries(iProject, jarFiles)); - return allocateContainer(javaProject, entries, new Path(CONTAINER_DEPENDENCIES), - "Android Dependencies"); + return allocateContainer(javaProject, entries, new Path(CONTAINER_DEPENDENCIES), + "Android Dependencies"); + } } private static IClasspathContainer allocateContainer(IJavaProject javaProject, diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java index 2fceffe..44827a0 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ProjectHelper.java @@ -28,6 +28,7 @@ import com.android.ide.eclipse.adt.internal.build.builders.PreCompilerBuilder; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; +import com.android.sdklib.IAndroidTarget; import com.android.utils.Pair; import org.eclipse.core.resources.ICommand; @@ -437,7 +438,7 @@ public final class ProjectHelper { String compliance = javaProject.getOption(JavaCore.COMPILER_COMPLIANCE, true); // check it against a list of valid compliance level strings. - if (checkCompliance(compliance) == false) { + if (!checkCompliance(javaProject, compliance)) { // if we didn't find the proper compliance level, we return an error return Pair.of(COMPILER_COMPLIANCE_LEVEL, compliance); } @@ -446,7 +447,7 @@ public final class ProjectHelper { String source = javaProject.getOption(JavaCore.COMPILER_SOURCE, true); // check it against a list of valid compliance level strings. - if (checkCompliance(source) == false) { + if (!checkCompliance(javaProject, source)) { // if we didn't find the proper compliance level, we return an error return Pair.of(COMPILER_COMPLIANCE_SOURCE, source); } @@ -455,7 +456,7 @@ public final class ProjectHelper { String codeGen = javaProject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true); // check it against a list of valid compliance level strings. - if (checkCompliance(codeGen) == false) { + if (!checkCompliance(javaProject, codeGen)) { // if we didn't find the proper compliance level, we return an error return Pair.of(COMPILER_COMPLIANCE_CODEGEN_TARGET, codeGen); } @@ -864,15 +865,26 @@ public final class ProjectHelper { /** * Checks a Java project compiler level option against a list of supported versions. * @param optionValue the Compiler level option. - * @return true if the option value is supproted. + * @return true if the option value is supported. */ - private static boolean checkCompliance(String optionValue) { + private static boolean checkCompliance(@NonNull IJavaProject project, String optionValue) { for (String s : AdtConstants.COMPILER_COMPLIANCE) { if (s != null && s.equals(optionValue)) { return true; } } + if (JavaCore.VERSION_1_7.equals(optionValue)) { + // Requires API 19 + Sdk currentSdk = Sdk.getCurrent(); + if (currentSdk != null) { + IAndroidTarget target = currentSdk.getTarget(project.getProject()); + if (target != null && target.getVersion().getApiLevel() >= 19) { + return true; + } + } + } + return false; } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java index 3b1fa52..8ecb088 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java @@ -25,7 +25,7 @@ import static com.android.SdkConstants.TAG_ITEM; import com.android.annotations.NonNull; import com.android.annotations.Nullable; -import com.android.ide.common.resources.ResourceRepository; +import com.android.ide.common.resources.ResourceUrl; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; @@ -33,7 +33,6 @@ import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; import com.android.ide.eclipse.adt.internal.sdk.ProjectState; import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.resources.ResourceType; -import com.android.utils.Pair; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -108,15 +107,15 @@ public final class RenameResourceXmlTextAction extends Action { return; } - Pair<ResourceType, String> resource = findResource(document, selection.getOffset()); + ResourceUrl resource = findResource(document, selection.getOffset()); if (resource == null) { resource = findItemDefinition(document, selection.getOffset()); } if (resource != null) { - ResourceType type = resource.getFirst(); - String name = resource.getSecond(); + ResourceType type = resource.type; + String name = resource.name; Shell shell = mEditor.getSite().getShell(); boolean canClear = false; @@ -176,7 +175,7 @@ public final class RenameResourceXmlTextAction extends Action { * @return a resource pair, or null if not found */ @Nullable - public static Pair<ResourceType,String> findResource(@NonNull IDocument document, int offset) { + public static ResourceUrl findResource(@NonNull IDocument document, int offset) { try { int max = document.getLength(); if (offset >= max) { @@ -220,7 +219,7 @@ public final class RenameResourceXmlTextAction extends Action { return null; } - return ResourceRepository.parseResource(url); + return ResourceUrl.parse(url); } } } catch (BadLocationException e) { @@ -238,7 +237,7 @@ public final class RenameResourceXmlTextAction extends Action { * Searches for an item definition around the caret, such as * {@code <string name="foo">My String</string>} */ - private Pair<ResourceType, String> findItemDefinition(IDocument document, int offset) { + private ResourceUrl findItemDefinition(IDocument document, int offset) { Node node = DomUtilities.getNode(document, offset); if (node == null) { return null; @@ -264,7 +263,7 @@ public final class RenameResourceXmlTextAction extends Action { } ResourceType type = ResourceType.getEnum(typeString); if (type != null) { - return Pair.of(type, name); + return ResourceUrl.create(type, name, false, false); } return null; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java index 978980b..8da18dd 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java @@ -34,8 +34,8 @@ import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP; import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.resources.ResourceDeltaKind; -import com.android.ide.common.resources.ResourceRepository; import com.android.ide.common.resources.ResourceResolver; +import com.android.ide.common.resources.ResourceUrl; import com.android.ide.common.resources.configuration.CountryCodeQualifier; import com.android.ide.common.resources.configuration.DensityQualifier; import com.android.ide.common.resources.configuration.FolderConfiguration; @@ -249,10 +249,13 @@ public class ResourceHelper { return false; } - Pair<ResourceType,String> parsed = ResourceRepository.parseResource(resource); + ResourceUrl parsed = ResourceUrl.parse(resource); if (parsed != null) { - ResourceType type = parsed.getFirst(); - String name = parsed.getSecond(); + if (parsed.framework) { + return false; + } + ResourceType type = parsed.type; + String name = parsed.name; // Make sure the name is valid ResourceNameValidator validator = diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java index f993d89..38460a4 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/manager/ProjectClassLoader.java @@ -33,6 +33,10 @@ import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; import java.io.File; import java.io.FileInputStream; @@ -144,9 +148,20 @@ public final class ProjectClassLoader extends ClassLoader { fis.close(); if (data != null) { - Class<?> clazz = defineClass(null, data, 0, read); - if (clazz != null) { - return clazz; + try { + Class<?> clazz = defineClass(null, data, 0, read); + if (clazz != null) { + return clazz; + } + } catch (UnsupportedClassVersionError e) { + // Attempt to reload on lower version + int maxVersion = 50; // JDK 1.6 + try { + byte[] rewritten = rewriteClass(data, maxVersion, 0); + return defineClass(null, rewritten, 0, rewritten.length); + } catch (UnsupportedClassVersionError e2) { + throw e; // throw *original* exception, not attempt to rewrite + } } } } catch (Exception e) { @@ -157,6 +172,30 @@ public final class ProjectClassLoader extends ClassLoader { } /** + * Rewrites the given class to the given target class file version. + */ + public static byte[] rewriteClass(byte[] classData, final int maxVersion, final int minVersion) { + assert maxVersion >= minVersion; + ClassWriter classWriter = new ClassWriter(0); + ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM4, classWriter) { + @Override + public void visit(int version, int access, String name, String signature, + String superName, String[] interfaces) { + if (version > maxVersion) { + version = maxVersion; + } + if (version < minVersion) { + version = minVersion; + } + super.visit(version, access, name, signature, superName, interfaces); + } + }; + ClassReader reader = new ClassReader(classData); + reader.accept(classVisitor, 0); + return classWriter.toByteArray(); + } + + /** * Returns the File matching the a certain path from a root {@link File}. * <p/>The methods checks that the file ends in .class even though the last segment * does not. diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java index c4eb37f..754cedf 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/AndroidJarLoader.java @@ -251,7 +251,16 @@ public class AndroidJarLoader extends ClassLoader implements IAndroidClassLoader } data = readZipData(zis, (int)entrySize); } - loaded_class = defineAndCacheClass(className, data); + try { + loaded_class = defineAndCacheClass(className, data); + } catch (NoClassDefFoundError error) { + if (error.getMessage().startsWith("java/")) { + // Can't define these; we just need to stop + // iteration here + continue; + } + throw error; + } } for (Class<?> superClass = loaded_class.getSuperclass(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java index 4628509..74c9857 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/ProjectState.java @@ -259,6 +259,15 @@ public final class ProjectState { return mProperties.getProperty(ProjectProperties.PROPERTY_BUILD_TOOLS); } + public boolean getRenderScriptSupportMode() { + String supportModeValue = mProperties.getProperty(ProjectProperties.PROPERTY_RS_SUPPORT); + if (supportModeValue != null) { + return Boolean.parseBoolean(supportModeValue); + } + + return false; + } + public static class LibraryDifference { public boolean removed = false; public boolean added = false; diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java index ca6cc57..c8faa5e 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/sdk/Sdk.java @@ -1187,6 +1187,7 @@ public final class Sdk { // get the current target and build tools IAndroidTarget oldTarget = state.getTarget(); + boolean oldRsSupportMode = state.getRenderScriptSupportMode(); // get the current library flag boolean wasLibrary = state.isLibrary(); @@ -1216,7 +1217,8 @@ public final class Sdk { } // apply the new target if needed. - if (newTarget != oldTarget) { + if (newTarget != oldTarget || + oldRsSupportMode != state.getRenderScriptSupportMode()) { IJavaProject javaProject = BaseProjectHelper.getJavaProject( file.getProject()); if (javaProject != null) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java index baa6b47..096b0b1 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/exportgradle/BuildFileCreator.java @@ -132,12 +132,18 @@ public class BuildFileCreator { IPath workspaceLocation = workspaceRoot.getLocation(); IPath relativePath = commonRoot.makeRelativeTo(workspaceLocation); + // if makeRelativePath to returns the same path, then commonRoot is not in the + // workspace. boolean rootInWorkspace = !relativePath.equals(commonRoot); + // we only care if the root is a workspace project. if it's the workspace folder itself, + // then the files won't be handled by the workspace. + rootInWorkspace = rootInWorkspace && relativePath.segmentCount() > 0; File settingsFile = new File(commonRoot.toFile(), SETTINGS_FILE); // more than one modules -> generate settings.gradle if (multiModules && rootInWorkspace) { + // Locate the settings.gradle file and add it to the changed files list IPath settingsGradle = Path.fromOSString(settingsFile.getAbsolutePath()); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ImportPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ImportPage.java index 6e63107..1e02fed 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ImportPage.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ImportPage.java @@ -206,6 +206,11 @@ class ImportPage extends WizardPage implements SelectionListener, IStructuredCon mCheckboxTableViewer.refresh(); mCheckboxTableViewer.setAllChecked(true); + updateValidity(); + validatePage(); + } + + private void updateValidity(){ List<ImportedProject> selected = new ArrayList<ImportedProject>(); List<ImportedProject> disabled = new ArrayList<ImportedProject>(); for (ImportedProject project : mProjectPaths) { @@ -230,7 +235,6 @@ class ImportPage extends WizardPage implements SelectionListener, IStructuredCon mCheckboxTableViewer.setCheckedElements(selected.toArray()); mCheckboxTableViewer.refresh(); mCheckboxTableViewer.getTable().setFocus(); - validatePage(); } private List<ImportedProject> searchForProjects(File dir) { @@ -242,7 +246,7 @@ class ImportPage extends WizardPage implements SelectionListener, IStructuredCon /** Finds all project directories under the given directory */ private void addProjects(File dir, List<ImportedProject> projects, int prefixLength) { if (dir.isDirectory()) { - if (LintUtils.isProjectDir(dir)) { + if (LintUtils.isManifestFolder(dir)) { String relative = dir.getPath(); if (relative.length() > prefixLength) { relative = relative.substring(prefixLength); @@ -485,6 +489,7 @@ class ImportPage extends WizardPage implements SelectionListener, IStructuredCon ImportedProject project = (ImportedProject) element; project.setProjectName(value.toString()); mCheckboxTableViewer.update(element, null); + updateValidity(); validatePage(); } 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 bd9c0fa..a875712 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 @@ -592,7 +592,7 @@ class TemplateHandler { if (relativePath != null && !relativePath.isEmpty()) { mOpen.add(relativePath); } - } else if (!name.equals("recipe")) { //$NON-NLS-1$ + } else if (!name.equals("recipe") && !name.equals(TAG_DEPENDENCY)) { //$NON-NLS-1$ System.err.println("WARNING: Unknown template directive " + name); } } catch (Exception e) { diff --git a/eclipse/plugins/com.android.ide.eclipse.base/.classpath b/eclipse/plugins/com.android.ide.eclipse.base/.classpath index 856475c..a81e5b5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.base/.classpath +++ b/eclipse/plugins/com.android.ide.eclipse.base/.classpath @@ -1,7 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry exported="true" kind="lib" path="libs/bcpkix-jdk15on-1.48.jar"/> - <classpathentry exported="true" kind="lib" path="libs/bcprov-jdk15on-1.48.jar"/> <classpathentry exported="true" kind="lib" path="libs/dvlib.jar" sourcepath="/dvlib"/> <classpathentry exported="true" kind="lib" path="libs/common.jar" sourcepath="/common"/> <classpathentry exported="true" kind="lib" path="libs/commons-codec-1.4.jar"/> diff --git a/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF index fc7fd5c..0cc6348 100644 --- a/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.base/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Common Android Utilities Bundle-SymbolicName: com.android.ide.eclipse.base;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime Bundle-ActivationPolicy: lazy diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF index 06ead0f..e956a16 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: com.android.ide.eclipse.ddms;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Activator: com.android.ide.eclipse.ddms.DdmsPlugin Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java index 13a4f99..c70c388 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java @@ -746,7 +746,8 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien if (data.hasFeature(ClientData.FEATURE_PROFILING)) { mTracingAction.setEnabled(true); - if (data.getMethodProfilingStatus() == MethodProfilingStatus.ON) { + if (data.getMethodProfilingStatus() == MethodProfilingStatus.TRACER_ON + || data.getMethodProfilingStatus() == MethodProfilingStatus.SAMPLER_ON) { mTracingAction .setToolTipText(Messages.DeviceView_Stop_Method_Profiling_Tooltip); mTracingAction.setText(Messages.DeviceView_Stop_Method_Profiling); diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger.tests/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.gldebugger.tests/META-INF/MANIFEST.MF index 84f1e79..fb7ba7f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.gldebugger.tests/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: gldebugger-tests Bundle-SymbolicName: com.android.ide.eclipse.gldebugger.tests -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-RequiredExecutionEnvironment: J2SE-1.5 Require-Bundle: org.junit4;bundle-version="4.5.0";resolution:=optional, com.android.ide.eclipse.gldebugger, diff --git a/eclipse/plugins/com.android.ide.eclipse.gldebugger/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.gldebugger/META-INF/MANIFEST.MF index 38bd875..0b7852f 100644 --- a/eclipse/plugins/com.android.ide.eclipse.gldebugger/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.gldebugger/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Tracer for OpenGL ES Bundle-SymbolicName: com.android.ide.eclipse.gldebugger;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Activator: com.android.ide.eclipse.gltrace.GlTracePlugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, diff --git a/eclipse/plugins/com.android.ide.eclipse.hierarchyviewer/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.hierarchyviewer/META-INF/MANIFEST.MF index b7566ba..7caacf5 100644 --- a/eclipse/plugins/com.android.ide.eclipse.hierarchyviewer/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.hierarchyviewer/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Hierarchy Viewer Bundle-SymbolicName: com.android.ide.eclipse.hierarchyviewer;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Activator: com.android.ide.eclipse.hierarchyviewer.HierarchyViewerPlugin Bundle-Vendor: The Android Open Source Project Bundle-Localization: plugin diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF index 3899c74..689da94 100644 --- a/eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.monitor/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: com.android.ide.eclipse.monitor;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Activator: com.android.ide.eclipse.monitor.MonitorPlugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/monitor.product b/eclipse/plugins/com.android.ide.eclipse.monitor/monitor.product index 703c4e3..03376e4 100644 --- a/eclipse/plugins/com.android.ide.eclipse.monitor/monitor.product +++ b/eclipse/plugins/com.android.ide.eclipse.monitor/monitor.product @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <?pde version="3.5"?> -<product name="monitor" uid="com.android.ide.eclipse.monitor.product.config" id="com.android.ide.eclipse.monitor.product" application="com.android.ide.eclipse.monitor.Application" version="22.0.0" useFeatures="false" includeLaunchers="true"> +<product name="monitor" uid="com.android.ide.eclipse.monitor.product.config" id="com.android.ide.eclipse.monitor.product" application="com.android.ide.eclipse.monitor.Application" version="22.3.0" useFeatures="false" includeLaunchers="true"> <configIni use="default"> diff --git a/eclipse/plugins/com.android.ide.eclipse.monitor/plugin.properties b/eclipse/plugins/com.android.ide.eclipse.monitor/plugin.properties index 39fe42d..4191caf 100644 --- a/eclipse/plugins/com.android.ide.eclipse.monitor/plugin.properties +++ b/eclipse/plugins/com.android.ide.eclipse.monitor/plugin.properties @@ -4,5 +4,5 @@ Bundle-Vendor = The Android Open Source Project Bundle-Name = Monitor aboutText = \n\ Android Device Monitor\n\ -Version: 22.0.0 \n\ +Version: 22.3.0 \n\ Copyright 2012, The Android Open Source Project \n\ diff --git a/eclipse/plugins/com.android.ide.eclipse.ndk/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.ndk/META-INF/MANIFEST.MF index 4590a42..10e3367 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ndk/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.ndk/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: ADT CDT Integration Bundle-SymbolicName: com.android.ide.eclipse.ndk;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Activator: com.android.ide.eclipse.ndk.internal.Activator Bundle-Vendor: The Android Open Source Project Require-Bundle: org.eclipse.core.runtime, diff --git a/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java b/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java index 651121a..0b124f2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java +++ b/eclipse/plugins/com.android.ide.eclipse.ndk/src/com/android/ide/eclipse/ndk/internal/launch/NdkGdbLaunchDelegate.java @@ -16,6 +16,8 @@ package com.android.ide.eclipse.ndk.internal.launch; +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; import com.android.ddmlib.AdbCommandRejectedException; import com.android.ddmlib.AndroidDebugBridge; import com.android.ddmlib.Client; @@ -30,7 +32,7 @@ import com.android.ide.common.xml.ManifestData; import com.android.ide.common.xml.ManifestData.Activity; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.internal.editors.manifest.ManifestInfo; -import com.android.ide.eclipse.adt.internal.launch.DeviceChoiceCache; +import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchController; import com.android.ide.eclipse.adt.internal.launch.DeviceChooserDialog; import com.android.ide.eclipse.adt.internal.launch.DeviceChooserDialog.DeviceChooserResponse; import com.android.ide.eclipse.adt.internal.launch.LaunchConfigDelegate; @@ -93,7 +95,7 @@ public class NdkGdbLaunchDelegate extends GdbLaunchDelegate { } } - public boolean doLaunch(ILaunchConfiguration config, String mode, ILaunch launch, + public boolean doLaunch(final ILaunchConfiguration config, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { IProject project = null; ICProject cProject = CDebugUtils.getCProject(config); @@ -151,9 +153,7 @@ public class NdkGdbLaunchDelegate extends GdbLaunchDelegate { IDevice[] devices = AndroidDebugBridge.getBridge().getDevices(); if (devices.length == 1) { device = devices[0]; - } else if (DeviceChoiceCache.get(configName) != null) { - device = DeviceChoiceCache.get(configName); - } else { + } else if ((device = getLastUsedDevice(config, devices)) == null) { final IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project); final DeviceChooserResponse response = new DeviceChooserResponse(); final boolean continueLaunch[] = new boolean[] { false }; @@ -164,9 +164,10 @@ public class NdkGdbLaunchDelegate extends GdbLaunchDelegate { AdtPlugin.getDisplay().getActiveShell(), response, manifestData.getPackage(), - projectTarget, minSdkVersion); + projectTarget, minSdkVersion, false /*** FIXME! **/); if (dialog.open() == Dialog.OK) { - DeviceChoiceCache.put(configName, response); + AndroidLaunchController.updateLaunchConfigWithLastUsedDevice(config, + response); continueLaunch[0] = true; } }; @@ -341,14 +342,32 @@ public class NdkGdbLaunchDelegate extends GdbLaunchDelegate { } // update launch attributes based on device - config = performVariableSubstitutions(config, project, compatAbi, monitor); + ILaunchConfiguration config2 = performVariableSubstitutions(config, project, compatAbi, + monitor); // launch gdb monitor.setTaskName(Messages.NdkGdbLaunchDelegate_Action_LaunchHostGdb); - super.launch(config, mode, launch, monitor); + super.launch(config2, mode, launch, monitor); return true; } + @Nullable + private IDevice getLastUsedDevice(ILaunchConfiguration config, @NonNull IDevice[] devices) { + try { + boolean reuse = config.getAttribute(LaunchConfigDelegate.ATTR_REUSE_LAST_USED_DEVICE, + false); + if (!reuse) { + return null; + } + + String serial = config.getAttribute(LaunchConfigDelegate.ATTR_LAST_USED_DEVICE, + (String)null); + return AndroidLaunchController.getDeviceIfOnline(serial, devices); + } catch (CoreException e) { + return null; + } + } + private void pull(IDevice device, String remote, IPath solibFolder) throws SyncException, IOException, AdbCommandRejectedException, TimeoutException { String remoteFileName = new Path(remote).toFile().getName(); diff --git a/eclipse/plugins/com.android.ide.eclipse.pdt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.pdt/META-INF/MANIFEST.MF index b6586aa..d2c7fa2 100644 --- a/eclipse/plugins/com.android.ide.eclipse.pdt/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.pdt/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Pdt Bundle-SymbolicName: com.android.ide.eclipse.pdt;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Vendor: The Android Open Source Project Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF index e40176a..4e9382c 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Android Plugin Tests Bundle-SymbolicName: com.android.ide.eclipse.tests -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Vendor: The Android Open Source Project Fragment-Host: com.android.ide.eclipse.adt;bundle-version="21.0.0" Require-Bundle: org.junit diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/HyperlinksTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/HyperlinksTest.java index cb83947..20aae84 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/HyperlinksTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/editors/HyperlinksTest.java @@ -54,23 +54,22 @@ public class HyperlinksTest extends AdtProjectTest { } public void testFqnRegexp() throws Exception { - assertTrue(Hyperlinks.CLASS_PATTERN.matcher("com.android.Foo").matches()); - assertTrue(Hyperlinks.CLASS_PATTERN.matcher("com.android.pk_g.Foo_Bar1"). - matches()); - assertTrue(Hyperlinks.CLASS_PATTERN.matcher("com.android.Foo$Inner").matches()); + assertTrue(Hyperlinks.isViewClassName("com.android.Foo")); + assertTrue(Hyperlinks.isViewClassName("com.android.pk_g.Foo_Bar1")); + assertTrue(Hyperlinks.isViewClassName("com.android.Foo$Inner")); // Should we allow non-standard packages and class names? // For now, we're allowing it -- see how this works out in practice. - //assertFalse(XmlHyperlinkResolver.CLASS_PATTERN.matcher("Foo.bar").matches()); - assertTrue(Hyperlinks.CLASS_PATTERN.matcher("Foo.bar").matches()); - - assertFalse(Hyperlinks.CLASS_PATTERN.matcher("LinearLayout").matches()); - assertFalse(Hyperlinks.CLASS_PATTERN.matcher(".").matches()); - assertFalse(Hyperlinks.CLASS_PATTERN.matcher(".F").matches()); - assertFalse(Hyperlinks.CLASS_PATTERN.matcher("f.").matches()); - assertFalse(Hyperlinks.CLASS_PATTERN.matcher("Foo").matches()); - assertFalse(Hyperlinks.CLASS_PATTERN.matcher("com.android.1Foo").matches()); - assertFalse(Hyperlinks.CLASS_PATTERN.matcher("1com.Foo").matches()); + //assertFalse(XmlHyperlinkResolver.isViewClassName("Foo.bar")); + assertTrue(Hyperlinks.isViewClassName("Foo.bar")); + + assertFalse(Hyperlinks.isViewClassName("LinearLayout")); + assertFalse(Hyperlinks.isViewClassName(".")); + assertFalse(Hyperlinks.isViewClassName(".F")); + assertFalse(Hyperlinks.isViewClassName("f.")); + assertFalse(Hyperlinks.isViewClassName("Foo")); + assertFalse(Hyperlinks.isViewClassName("com.android.1Foo")); + assertFalse(Hyperlinks.isViewClassName("1com.Foo")); } public void testNavigate1() throws Exception { diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java index ccf6e4f..3f029b9 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java @@ -16,10 +16,9 @@ package com.android.ide.eclipse.adt.internal.refactorings.core; import com.android.annotations.NonNull; -import com.android.ide.common.resources.ResourceRepository; +import com.android.ide.common.resources.ResourceUrl; import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; import com.android.resources.ResourceType; -import com.android.utils.Pair; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -366,10 +365,12 @@ public class RenameResourceParticipantTest extends RefactoringTestBase { if (resource instanceof String) { String url = (String) resource; assert url.startsWith("@") : resource; - Pair<ResourceType, String> pair = ResourceRepository.parseResource(url); - assertNotNull(url, pair); - ResourceType type = pair.getFirst(); - String currentName = pair.getSecond(); + + ResourceUrl parsedUrl = ResourceUrl.parse(url); + assertNotNull(url, parsedUrl); + assert parsedUrl != null; // null analysis doesn't recognize assertNotNull + ResourceType type = parsedUrl.type; + String currentName = parsedUrl.name; RenameResourceProcessor p; p = new RenameResourceProcessor(project, type, currentName, newName); p.setUpdateReferences(updateReferences); diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLoggerTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLoggerTest.java index 5748791..c28d9a9 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLoggerTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderLoggerTest.java @@ -20,12 +20,12 @@ import junit.framework.TestCase; public class RenderLoggerTest extends TestCase { public void testLogger1() throws Exception { - RenderLogger l = new RenderLogger("foo"); + RenderLogger l = new RenderLogger("foo", null); assertFalse(l.hasProblems()); } public void testLogger2() throws Exception { - RenderLogger l = new RenderLogger("foo"); + RenderLogger l = new RenderLogger("foo", null); assertFalse(l.hasProblems()); l.fidelityWarning(null, "No perspective Transforms", null, null); l.fidelityWarning(null, "No GPS", null, null); @@ -37,7 +37,7 @@ public class RenderLoggerTest extends TestCase { } public void testLogger3() throws Exception { - RenderLogger l = new RenderLogger("foo"); + RenderLogger l = new RenderLogger("foo", null); assertFalse(l.hasProblems()); l.error("timeout", "Sample Error", new RuntimeException(), null); l.warning("slow", "Sample warning", null); @@ -56,7 +56,7 @@ public class RenderLoggerTest extends TestCase { } public void testLoggerSuppressWarnings() throws Exception { - RenderLogger l = new RenderLogger("foo"); + RenderLogger l = new RenderLogger("foo", null); assertFalse(l.hasProblems()); RenderLogger.ignoreFidelityWarning("No perspective Transforms"); l.fidelityWarning(null, "No perspective Transforms", null, null); @@ -68,7 +68,7 @@ public class RenderLoggerTest extends TestCase { assertFalse(l.seenTag("foo")); assertFalse(l.seenTag(null)); - l = new RenderLogger("foo"); + l = new RenderLogger("foo", null); assertFalse(l.hasProblems()); RenderLogger.ignoreFidelityWarning("No perspective Transforms"); RenderLogger.ignoreFidelityWarning("No GPS"); diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextActionTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextActionTest.java index 11fc81a..e00a44b 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextActionTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextActionTest.java @@ -15,8 +15,8 @@ */ package com.android.ide.eclipse.adt.internal.refactorings.core; +import com.android.ide.common.resources.ResourceUrl; import com.android.resources.ResourceType; -import com.android.utils.Pair; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.IDocument; @@ -31,25 +31,29 @@ public class RenameResourceXmlTextActionTest extends TestCase { checkWord("^@bogus", null); checkWord("@bo^gus", null); checkWord("bogus@^", null); - checkWord(" @string/nam^e ", Pair.of(ResourceType.STRING, "name")); - checkWord("@string/nam^e ", Pair.of(ResourceType.STRING, "name")); - checkWord("\"^@string/name ", Pair.of(ResourceType.STRING, "name")); - checkWord("^@string/name ", Pair.of(ResourceType.STRING, "name")); - checkWord("\n^@string/name ", Pair.of(ResourceType.STRING, "name")); - checkWord("\n^@string/name(", Pair.of(ResourceType.STRING, "name")); - checkWord("\n^@string/name;", Pair.of(ResourceType.STRING, "name")); - checkWord("\n^@string/name5", Pair.of(ResourceType.STRING, "name5")); - checkWord("\n@string/name5^", Pair.of(ResourceType.STRING, "name5")); - checkWord("\n@string/name5^(", Pair.of(ResourceType.STRING, "name5")); - checkWord("\n@stri^ng/name5(", Pair.of(ResourceType.STRING, "name5")); - checkWord("\n@string^/name5(", Pair.of(ResourceType.STRING, "name5")); - checkWord("\n@string/^name5(", Pair.of(ResourceType.STRING, "name5")); + checkWord(" @string/nam^e ", getUrl(ResourceType.STRING, "name")); + checkWord("@string/nam^e ", getUrl(ResourceType.STRING, "name")); + checkWord("\"^@string/name ", getUrl(ResourceType.STRING, "name")); + checkWord("^@string/name ", getUrl(ResourceType.STRING, "name")); + checkWord("\n^@string/name ", getUrl(ResourceType.STRING, "name")); + checkWord("\n^@string/name(", getUrl(ResourceType.STRING, "name")); + checkWord("\n^@string/name;", getUrl(ResourceType.STRING, "name")); + checkWord("\n^@string/name5", getUrl(ResourceType.STRING, "name5")); + checkWord("\n@string/name5^", getUrl(ResourceType.STRING, "name5")); + checkWord("\n@string/name5^(", getUrl(ResourceType.STRING, "name5")); + checkWord("\n@stri^ng/name5(", getUrl(ResourceType.STRING, "name5")); + checkWord("\n@string^/name5(", getUrl(ResourceType.STRING, "name5")); + checkWord("\n@string/^name5(", getUrl(ResourceType.STRING, "name5")); checkWord("\n@string^name5(", null); checkWord("\n@strings^/name5(", null); - checkWord("\n@+id/^myid(", Pair.of(ResourceType.ID, "myid")); - checkWord("\n?a^ttr/foo\"", Pair.of(ResourceType.ATTR, "foo")); - checkWord("\n?f^oo\"", Pair.of(ResourceType.ATTR, "foo")); - checkWord("\n^?foo\"", Pair.of(ResourceType.ATTR, "foo")); + checkWord("\n@+id/^myid(", getUrl(ResourceType.ID, "myid")); + checkWord("\n?a^ttr/foo\"", getUrl(ResourceType.ATTR, "foo")); + checkWord("\n?f^oo\"", getUrl(ResourceType.ATTR, "foo")); + checkWord("\n^?foo\"", getUrl(ResourceType.ATTR, "foo")); + } + + private static ResourceUrl getUrl(ResourceType type, String name) { + return ResourceUrl.create(type, name, false, false); } public void testClassNames() throws Exception { @@ -89,7 +93,7 @@ public class RenameResourceXmlTextActionTest extends TestCase { assertEquals(expectedClassName, className); } - private void checkWord(String contents, Pair<ResourceType, String> expectedResource) + private void checkWord(String contents, ResourceUrl expectedResource) throws Exception { int cursor = contents.indexOf('^'); assertTrue("Must set cursor position with ^ in " + contents, cursor != -1); @@ -100,8 +104,7 @@ public class RenameResourceXmlTextActionTest extends TestCase { IDocument document = new Document(); document.replace(0, 0, contents); - Pair<ResourceType, String> resource = - RenameResourceXmlTextAction.findResource(document, cursor); + ResourceUrl resource = RenameResourceXmlTextAction.findResource(document, cursor); assertEquals(expectedResource, resource); } } diff --git a/eclipse/plugins/com.android.ide.eclipse.traceview/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.traceview/META-INF/MANIFEST.MF index 89214ee..4686211 100644 --- a/eclipse/plugins/com.android.ide.eclipse.traceview/META-INF/MANIFEST.MF +++ b/eclipse/plugins/com.android.ide.eclipse.traceview/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Traceview Bundle-SymbolicName: com.android.ide.eclipse.traceview;singleton:=true -Bundle-Version: 22.0.0.qualifier +Bundle-Version: 22.3.0.qualifier Bundle-Activator: com.android.ide.eclipse.traceview.TraceviewPlugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, diff --git a/eclipse/scripts/build_server.sh b/eclipse/scripts/build_server.sh index e96abe1..54deaa6 100755 --- a/eclipse/scripts/build_server.sh +++ b/eclipse/scripts/build_server.sh @@ -64,7 +64,8 @@ function check_params() { # Qualifier is "v" followed by date/time in YYYYMMDDHHSS format, an optional "preview" # tag and the optional build number. DATE=`date +v%Y%m%d%H%M` - QUALIFIER="${DATE}-$ADT_PREVIEW" + local preview="${ADT_PREVIEW:+-}${ADT_PREVIEW}" + QUALIFIER="${DATE}${preview}" [ -n "$BUILD_NUMBER" ] && QUALIFIER="${QUALIFIER}-${BUILD_NUMBER}" return 0 @@ -118,7 +119,9 @@ function build_adt_ide() { # This needs to run from the top android directory D="$PROG_DIR" cd "$D/../../../" && echo "Switched to directory $PWD" - for sc in */*/*/build_ide*.sh; do + + IDE_SCRIPTS="sdk/eclipse/scripts/build_ide.sh tools/idea/build_ide_ext.sh" + for sc in $IDE_SCRIPTS; do if [[ -x $sc ]]; then echo "RUNNING $sc from $PWD" $sc "$DEST_DIR" "$QUALIFIER" "${preview}${BUILD_NUMBER:-$QUALIFIER}" diff --git a/eclipse/scripts/create_all_symlinks.sh b/eclipse/scripts/create_all_symlinks.sh index acdd3c2..80eaa54 100755 --- a/eclipse/scripts/create_all_symlinks.sh +++ b/eclipse/scripts/create_all_symlinks.sh @@ -283,8 +283,8 @@ fi # Otherwise we do a specific tools/base build on just the requested targets. if [[ -n "$GRADLE_SWT" ]]; then - echo "### Starting tools/base: gradlew publishLocal" - (cd tools/base && ./gradlew publishLocal) + echo "### Starting tools/base: gradlew assemble publishLocal" + (cd tools/base && ./gradlew assemble publishLocal) elif [[ -n "$GRADLE_BASE" ]]; then echo "### Starting tools/base: gradlew $GRADLE_BASE" (cd tools/base && ./gradlew $GRADLE_BASE) diff --git a/eclipse/scripts/update_version.sh b/eclipse/scripts/update_version.sh index 160aa0d..5b54c99 100755 --- a/eclipse/scripts/update_version.sh +++ b/eclipse/scripts/update_version.sh @@ -2,7 +2,6 @@ OLD="$1" NEW="$2" -REALOLD="$1" # sanity check in input args if [ -z "$OLD" ] || [ -z "$NEW" ]; then @@ -22,17 +21,55 @@ if [ `basename "$PWD"` != "eclipse" ]; then exit 1 fi +# sanity check the new version number +if [[ "$NEW" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "## Version $NEW: seems valid." +else + echo "## Version $NEW: does not conform to major.mino.micro format." + exit 1 +fi + +function replace() { + if [[ -f "$1" ]]; then + echo "### Change $SED_OLD => $SED_NEW in $1" + if [[ $(uname) == "Linux" ]]; then + sed -i "s/$SED_OLD/$SED_NEW/g" "$1" + else + # sed on Mac doesn't handle -i the same way as on Linux + sed -i "" "s/$SED_OLD/$SED_NEW/g" "$1" + fi + fi +} + +# ---1--- Change Eclipse's qualified version numbers # quote dots for regexps -OLD="${OLD//./\.}\.qualifier" -NEW="${NEW//./\.}\.qualifier" +SED_OLD="${OLD//./\.}\.qualifier" +SED_NEW="${NEW//./\.}\.qualifier" + +for i in $(grep -rl "$OLD" * | grep -E "\.xml$|\.MF$"); do + if [[ -f "$i" && $(basename "$i") != "build.xml" ]]; then + replace "$i" + fi +done -# Now find the same files but this time use sed to replace in-place with -# the new pattern. Old files get backuped with the .old extension. -grep -rl "$OLD" * | grep -E "\.xml$|\.MF$" | xargs -n 1 sed -i "" "s/$OLD/$NEW/g" +# ---2--- Change unqualified version numbers in specific files +SED_OLD="${OLD//./\.}" +SED_NEW="${NEW//./\.}" +for i in plugins/com.android.ide.eclipse.adt.package/ide.product \ + plugins/com.android.ide.eclipse.monitor/monitor.product \ + plugins/com.android.ide.eclipse.monitor/plugin.properties; do + if grep -qs "$OLD" "$i"; then + replace "$i" + fi +done -echo "Remaining instances of $REALOLD" # do another grep for older version without the qualifier. We don't # want to replace those automatically as it could be something else. -# Printing out occurence helps find ones to update manually. -grep -r "$REALOLD" * +# Printing out occurence helps find ones to update manually, but exclude +# some known useless files. +echo +echo "#### ----------------" +echo "#### Remaining instances of $OLD" +echo +grep -r "$OLD" * | grep -v -E "/build.xml:|/javaCompiler\.\.\.args:" diff --git a/eclipse/sites/external/site.xml b/eclipse/sites/external/site.xml index bb5e7b6..17033d9 100644 --- a/eclipse/sites/external/site.xml +++ b/eclipse/sites/external/site.xml @@ -3,22 +3,22 @@ <description url="https://dl-ssl.google.com/android/eclipse/"> Update Site for Android Development Toolkit </description> - <feature url="features/com.android.ide.eclipse.adt_22.0.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.adt_22.3.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="22.3.0.qualifier"> <category name="developer"/> </feature> - <feature url="features/com.android.ide.eclipse.ddms_22.0.0.qualifier.jar" id="com.android.ide.eclipse.ddms" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.ddms_22.3.0.qualifier.jar" id="com.android.ide.eclipse.ddms" version="22.3.0.qualifier"> <category name="developer"/> </feature> - <feature url="features/com.android.ide.eclipse.hierarchyviewer_22.0.0.qualifier.jar" id="com.android.ide.eclipse.hierarchyviewer" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.hierarchyviewer_22.3.0.qualifier.jar" id="com.android.ide.eclipse.hierarchyviewer" version="22.3.0.qualifier"> <category name="developer"/> </feature> - <feature url="features/com.android.ide.eclipse.traceview_22.0.0.qualifier.jar" id="com.android.ide.eclipse.traceview" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.traceview_22.3.0.qualifier.jar" id="com.android.ide.eclipse.traceview" version="22.3.0.qualifier"> <category name="developer"/> </feature> - <feature url="features/com.android.ide.eclipse.gldebugger_22.0.0.qualifier.jar" id="com.android.ide.eclipse.gldebugger" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.gldebugger_22.3.0.qualifier.jar" id="com.android.ide.eclipse.gldebugger" version="22.3.0.qualifier"> <category name="developer"/> </feature> - <feature url="features/com.android.ide.eclipse.ndk_22.0.0.qualifier.jar" id="com.android.ide.eclipse.ndk" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.ndk_22.3.0.qualifier.jar" id="com.android.ide.eclipse.ndk" version="22.3.0.qualifier"> <category name="ndk"/> </feature> <category-def name="developer" label="Developer Tools"> diff --git a/eclipse/sites/internal/site.xml b/eclipse/sites/internal/site.xml index 85fdc2f..c91db12 100644 --- a/eclipse/sites/internal/site.xml +++ b/eclipse/sites/internal/site.xml @@ -3,32 +3,32 @@ <description url="https://android.corp.google.com/adt/"> Update Site for Android Development Toolkit </description> - <feature url="features/com.android.ide.eclipse.adt_22.0.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.adt_22.3.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="22.3.0.qualifier"> <category name="developer"/> </feature> - <feature url="features/com.android.ide.eclipse.ddms_22.0.0.qualifier.jar" id="com.android.ide.eclipse.ddms" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.ddms_22.3.0.qualifier.jar" id="com.android.ide.eclipse.ddms" version="22.3.0.qualifier"> <category name="developer"/> <category name="platform"/> </feature> - <feature url="features/com.android.ide.eclipse.hierarchyviewer_22.0.0.qualifier.jar" id="com.android.ide.eclipse.hierarchyviewer" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.hierarchyviewer_22.3.0.qualifier.jar" id="com.android.ide.eclipse.hierarchyviewer" version="22.3.0.qualifier"> <category name="developer"/> <category name="platform"/> </feature> - <feature url="features/com.android.ide.eclipse.tests_22.0.0.qualifier.jar" id="com.android.ide.eclipse.tests" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.tests_22.3.0.qualifier.jar" id="com.android.ide.eclipse.tests" version="22.3.0.qualifier"> <category name="test"/> </feature> - <feature url="features/com.android.ide.eclipse.pdt_22.0.0.qualifier.jar" id="com.android.ide.eclipse.pdt" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.pdt_22.3.0.qualifier.jar" id="com.android.ide.eclipse.pdt" version="22.3.0.qualifier"> <category name="platform"/> </feature> - <feature url="features/com.android.ide.eclipse.traceview_22.0.0.qualifier.jar" id="com.android.ide.eclipse.traceview" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.traceview_22.3.0.qualifier.jar" id="com.android.ide.eclipse.traceview" version="22.3.0.qualifier"> <category name="developer"/> <category name="platform"/> </feature> - <feature url="features/com.android.ide.eclipse.gldebugger_22.0.0.qualifier.jar" id="com.android.ide.eclipse.gldebugger" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.gldebugger_22.3.0.qualifier.jar" id="com.android.ide.eclipse.gldebugger" version="22.3.0.qualifier"> <category name="developer"/> <category name="platform"/> </feature> - <feature url="features/com.android.ide.eclipse.ndk_22.0.0.qualifier.jar" id="com.android.ide.eclipse.ndk" version="22.0.0.qualifier"> + <feature url="features/com.android.ide.eclipse.ndk_22.3.0.qualifier.jar" id="com.android.ide.eclipse.ndk" version="22.3.0.qualifier"> <category name="developer"/> <category name="platform"/> </feature> diff --git a/emulator/opengl/host/libs/Translator/EGL/EglMacApi.cpp b/emulator/opengl/host/libs/Translator/EGL/EglMacApi.cpp index fd3cb0b..eeaa25c 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglMacApi.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglMacApi.cpp @@ -68,7 +68,15 @@ static EglConfig* pixelFormatToConfig(int index,int renderableType,EGLNativePixe getPixelFormatAttrib(*frmt,MAC_SAMPLES_PER_PIXEL,&samples); getPixelFormatAttrib(*frmt,MAC_COLOR_SIZE,&colorSize); - getPixelFormatAttrib(*frmt,MAC_ALPHA_SIZE,&alpha); + /* All configs can end up having an alpha channel even if none was requested. + * The default config chooser in GLSurfaceView will therefore not find any + * matching config. Thus, make sure alpha is zero (or at least signalled as + * zero to the calling EGL layer) for the configs where it was intended to + * be zero. */ + if (getPixelFormatDefinitionAlpha(index) == 0) + alpha = 0; + else + getPixelFormatAttrib(*frmt,MAC_ALPHA_SIZE,&alpha); getPixelFormatAttrib(*frmt,MAC_DEPTH_SIZE,&depth); getPixelFormatAttrib(*frmt,MAC_STENCIL_SIZE,&stencil); @@ -142,11 +150,20 @@ bool checkPixmapPixelFormatMatch(EGLNativeDisplayType dpy,EGLNativePixmapType pi EGLNativeSurfaceType createPbufferSurface(EGLNativeDisplayType dpy,EglConfig* cfg,EglPbufferSurface* srfc){ EGLint width,height,hasMipmap,tmp; EGLint target,format; + GLenum glTexFormat = GL_RGBA, glTexTarget = GL_TEXTURE_2D; srfc->getDim(&width,&height,&tmp); srfc->getTexInfo(&format,&target); + switch (format) { + case EGL_TEXTURE_RGB: + glTexFormat = GL_RGB; + break; + case EGL_TEXTURE_RGBA: + glTexFormat = GL_RGBA; + break; + } srfc->getAttrib(EGL_MIPMAP_TEXTURE,&hasMipmap); EGLint maxMipmap = hasMipmap ? MAX_PBUFFER_MIPMAP_LEVEL:0; - return (EGLNativeSurfaceType)nsCreatePBuffer(target,format,maxMipmap,width,height); + return (EGLNativeSurfaceType)nsCreatePBuffer(glTexTarget,glTexFormat,maxMipmap,width,height); } bool releasePbuffer(EGLNativeDisplayType dis,EGLNativeSurfaceType pb) { diff --git a/emulator/opengl/host/libs/Translator/EGL/MacNative.h b/emulator/opengl/host/libs/Translator/EGL/MacNative.h index 82ab667..c8a1df2 100644 --- a/emulator/opengl/host/libs/Translator/EGL/MacNative.h +++ b/emulator/opengl/host/libs/Translator/EGL/MacNative.h @@ -33,6 +33,7 @@ extern "C"{ int getNumPixelFormats(); void* getPixelFormat(int i); +int getPixelFormatDefinitionAlpha(int i); void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val); void* nsCreateContext(void* format,void* share); void nsWindowMakeCurrent(void* context,void* nativeWin); diff --git a/emulator/opengl/host/libs/Translator/EGL/MacNative.m b/emulator/opengl/host/libs/Translator/EGL/MacNative.m index 6828655..a2cea93 100644 --- a/emulator/opengl/host/libs/Translator/EGL/MacNative.m +++ b/emulator/opengl/host/libs/Translator/EGL/MacNative.m @@ -75,6 +75,34 @@ void* getPixelFormat(int i){ return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrib_lists[i]]; } +int getPixelFormatDefinitionAlpha(int i) { + int size; + NSOpenGLPixelFormatAttribute** attrib_lists = getPixelFormatsAttributes(&size); + NSOpenGLPixelFormatAttribute* attribs = attrib_lists[i]; + while (*attribs) { + switch (*attribs) { + // These are the ones that take a value, according to the current + // NSOpenGLPixelFormat docs + case NSOpenGLPFAAuxBuffers: + case NSOpenGLPFAColorSize: + case NSOpenGLPFADepthSize: + case NSOpenGLPFAStencilSize: + case NSOpenGLPFAAccumSize: + case NSOpenGLPFARendererID: + case NSOpenGLPFAScreenMask: + attribs += 2; + break; + case NSOpenGLPFAAlphaSize: + return attribs[1]; + break; + // All other attributes are boolean attributes that don't take a value + default: + attribs++; + } + } + return 0; +} + void getPixelFormatAttrib(void* pixelFormat,int attrib,int* val){ NSOpenGLPixelFormat *frmt = (NSOpenGLPixelFormat *)pixelFormat; [frmt getValues:val forAttribute:attrib forVirtualScreen:0]; diff --git a/emulator/opengl/host/libs/Translator/GLcommon/RangeManip.cpp b/emulator/opengl/host/libs/Translator/GLcommon/RangeManip.cpp index 5ba609b..2d6f119 100644 --- a/emulator/opengl/host/libs/Translator/GLcommon/RangeManip.cpp +++ b/emulator/opengl/host/libs/Translator/GLcommon/RangeManip.cpp @@ -35,13 +35,14 @@ bool Range::rangeUnion(const Range& r,Range& rOut) const { int size = max_end - min_start; if(size) { rOut.setRange(min_start,max_end-min_start); - return false; + return true; } return false; } void RangeList::addRange(const Range& r) { - list.push_back(r); + if(r.getSize()) + list.push_back(r); } void RangeList::addRanges(const RangeList& rl) { diff --git a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp index 5f04a97..46c5acf 100644 --- a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.cpp @@ -115,24 +115,8 @@ ColorBuffer::ColorBuffer() : m_eglImage(NULL), m_blitEGLImage(NULL), m_fbo(0), - m_internalFormat(0), - m_warYInvertBug(false) + m_internalFormat(0) { -#if __APPLE__ - // On Macs running OS X 10.6 and 10.7 with Intel HD Graphics 3000 or 4000, - // some screens or parts of the screen are displayed upside down. The exact - // conditions/sequence that triggers this aren't known yet; I haven't been - // able to reproduce it in a standalone test. This way of enabling the - // workaround will break if it is a driver bug (rather than a bug in this - // code which works by accident elsewhere) and Apple/Intel release a fix - // for it. Running a standalone test to detect the problem at runtime would - // be more robust. - const char* renderer = (const char*)s_gl.glGetString(GL_RENDERER); - if (strstr(renderer, "Intel HD Graphics 3000") || - strstr(renderer, "Intel HD Graphics 4000")) { - m_warYInvertBug = true; - } -#endif } ColorBuffer::~ColorBuffer() @@ -225,7 +209,7 @@ bool ColorBuffer::blitFromCurrentReadBuffer() s_gl.glBindTexture(GL_TEXTURE_2D, m_blitTex); s_gl.glEnable(GL_TEXTURE_2D); s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - drawTexQuad(!m_warYInvertBug); + drawTexQuad(); // this will render the texture flipped // unbind the fbo s_gl.glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0); @@ -325,12 +309,12 @@ bool ColorBuffer::post() s_gl.glBindTexture(GL_TEXTURE_2D, m_tex); s_gl.glEnable(GL_TEXTURE_2D); s_gl.glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); - drawTexQuad(true); + drawTexQuad(); return true; } -void ColorBuffer::drawTexQuad(bool flipy) +void ColorBuffer::drawTexQuad() { GLfloat verts[] = { -1.0f, -1.0f, 0.0f, -1.0f, +1.0f, 0.0f, @@ -342,13 +326,6 @@ void ColorBuffer::drawTexQuad(bool flipy) 1.0f, 1.0f, 1.0f, 0.0f }; - if (!flipy) { - for (int i = 0; i < 4; i++) { - // swap 0.0/1.0 in second element of each tcoord vector - tcoords[2*i + 1] = tcoords[2*i + 1] == 0.0f ? 1.0f : 0.0f; - } - } - s_gl.glClientActiveTexture(GL_TEXTURE0); s_gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY); s_gl.glTexCoordPointer(2, GL_FLOAT, 0, tcoords); diff --git a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h index d481891..883162b 100644 --- a/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h +++ b/emulator/opengl/host/libs/libOpenglRender/ColorBuffer.h @@ -41,7 +41,7 @@ public: private: ColorBuffer(); - void drawTexQuad(bool flipy); + void drawTexQuad(); bool bind_fbo(); // binds a fbo which have this texture as render target private: @@ -53,7 +53,6 @@ private: GLuint m_height; GLuint m_fbo; GLenum m_internalFormat; - bool m_warYInvertBug; }; typedef SmartPtr<ColorBuffer> ColorBufferPtr; diff --git a/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp b/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp index 089f1da..ca7351e 100644 --- a/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/FBConfig.cpp @@ -203,7 +203,9 @@ int FBConfig::chooseConfig(FrameBuffer *fb, EGLint * attribs, uint32_t * configs } #endif - s_egl.eglChooseConfig(dpy, newAttribs, matchedConfigs, nConfigs, &nConfigs); + if (!s_egl.eglChooseConfig(dpy, newAttribs, matchedConfigs, nConfigs, &nConfigs)) { + nConfigs = 0; + } delete[] newAttribs; diff --git a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp index 2c9e8c5..cfadf12 100644 --- a/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/FrameBuffer.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "FrameBuffer.h" #include "NativeSubWindow.h" #include "FBConfig.h" @@ -20,14 +21,14 @@ #include "GLDispatch.h" #include "GL2Dispatch.h" #include "ThreadInfo.h" -#include <stdio.h> #include "TimeUtils.h" +#include <stdio.h> FrameBuffer *FrameBuffer::s_theFrameBuffer = NULL; HandleType FrameBuffer::s_nextHandle = 0; #ifdef WITH_GLES2 -static const char *getGLES2ExtensionString(EGLDisplay p_dpy) +static char* getGLES2ExtensionString(EGLDisplay p_dpy) { EGLConfig config; EGLSurface surface; @@ -74,10 +75,9 @@ static const char *getGLES2ExtensionString(EGLDisplay p_dpy) return NULL; } - const char *extString = (const char *)s_gl2.glGetString(GL_EXTENSIONS); - if (!extString) { - extString = ""; - } + // the string pointer may become invalid when the context is destroyed + const char* s = (const char*)s_gl2.glGetString(GL_EXTENSIONS); + char* extString = strdup(s ? s : ""); s_egl.eglMakeCurrent(p_dpy, NULL, NULL, NULL); s_egl.eglDestroyContext(p_dpy, ctx); @@ -153,7 +153,7 @@ bool FrameBuffer::initialize(int width, int height) // if GLES2 plugin has loaded - try to make GLES2 context and // get GLES2 extension string // - const char *gl2Extensions = NULL; + char* gl2Extensions = NULL; #ifdef WITH_GLES2 if (fb->m_caps.hasGL2) { gl2Extensions = getGLES2ExtensionString(fb->m_eglDisplay); @@ -187,6 +187,7 @@ bool FrameBuffer::initialize(int width, int height) if (!s_egl.eglChooseConfig(fb->m_eglDisplay, configAttribs, &fb->m_eglConfig, 1, &n)) { ERR("Failed on eglChooseConfig\n"); + free(gl2Extensions); delete fb; return false; } @@ -201,6 +202,7 @@ bool FrameBuffer::initialize(int width, int height) glContextAttribs); if (fb->m_eglContext == EGL_NO_CONTEXT) { printf("Failed to create Context 0x%x\n", s_egl.eglGetError()); + free(gl2Extensions); delete fb; return false; } @@ -218,6 +220,7 @@ bool FrameBuffer::initialize(int width, int height) glContextAttribs); if (fb->m_pbufContext == EGL_NO_CONTEXT) { printf("Failed to create Pbuffer Context 0x%x\n", s_egl.eglGetError()); + free(gl2Extensions); delete fb; return false; } @@ -238,6 +241,7 @@ bool FrameBuffer::initialize(int width, int height) pbufAttribs); if (fb->m_pbufSurface == EGL_NO_SURFACE) { printf("Failed to create pbuf surface for FB 0x%x\n", s_egl.eglGetError()); + free(gl2Extensions); delete fb; return false; } @@ -245,6 +249,7 @@ bool FrameBuffer::initialize(int width, int height) // Make the context current if (!fb->bind_locked()) { ERR("Failed to make current\n"); + free(gl2Extensions); delete fb; return false; } @@ -259,8 +264,10 @@ bool FrameBuffer::initialize(int width, int height) } if (fb->m_caps.hasGL2 && has_gl_oes_image) { - has_gl_oes_image &= (strstr(gl2Extensions, "GL_OES_EGL_image") != NULL); + has_gl_oes_image &= strstr(gl2Extensions, "GL_OES_EGL_image") != NULL; } + free(gl2Extensions); + gl2Extensions = NULL; const char *eglExtensions = s_egl.eglQueryString(fb->m_eglDisplay, EGL_EXTENSIONS); @@ -578,9 +585,7 @@ bool FrameBuffer::flushWindowSurfaceColorBuffer(HandleType p_surface) return false; } - (*w).second->flushColorBuffer(); - - return true; + return (*w).second->flushColorBuffer(); } bool FrameBuffer::setWindowSurfaceColorBuffer(HandleType p_surface, diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp b/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp index 960dec7..6a15138 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/RenderControl.cpp @@ -239,7 +239,9 @@ static int rcFlushWindowColorBuffer(uint32_t windowSurface) if (!fb) { return -1; } - fb->flushWindowSurfaceColorBuffer(windowSurface); + if (!fb->flushWindowSurfaceColorBuffer(windowSurface)) { + return -1; + } return 0; } diff --git a/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp b/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp index 3674120..9c32ff8 100644 --- a/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/WindowSurface.cpp @@ -81,11 +81,12 @@ WindowSurface *WindowSurface::create(int p_config, int p_width, int p_height) // previous attached color buffer is updated, if copy or blit should be done // in order to update it - it is being done here. // -void WindowSurface::flushColorBuffer() +bool WindowSurface::flushColorBuffer() { if (m_attachedColorBuffer.Ptr() != NULL) { - blitToColorBuffer(); + return blitToColorBuffer(); } + return true; } // @@ -140,14 +141,15 @@ void WindowSurface::bind(RenderContextPtr p_ctx, SurfaceBindType p_bindType) } -void WindowSurface::blitToColorBuffer() +bool WindowSurface::blitToColorBuffer() { - if (!m_width && !m_height) return; + if (!m_width && !m_height) return false; if (m_attachedColorBuffer->getWidth() != m_width || m_attachedColorBuffer->getHeight() != m_height) { // XXX: should never happen - how this needs to be handled? - return; + fprintf(stderr, "Dimensions do not match\n"); + return false; } // @@ -157,9 +159,14 @@ void WindowSurface::blitToColorBuffer() EGLSurface prevReadSurf = s_egl.eglGetCurrentSurface(EGL_READ); EGLSurface prevDrawSurf = s_egl.eglGetCurrentSurface(EGL_DRAW); FrameBuffer *fb = FrameBuffer::getFB(); + if (!m_drawContext.Ptr()) { + fprintf(stderr, "Draw context is NULL\n"); + return false; + } if (!s_egl.eglMakeCurrent(fb->getDisplay(), m_eglSurface, m_eglSurface, m_drawContext->getEGLContext())) { - return; + fprintf(stderr, "Error making draw context current\n"); + return false; } m_attachedColorBuffer->blitFromCurrentReadBuffer(); @@ -167,12 +174,12 @@ void WindowSurface::blitToColorBuffer() // restore current context/surface s_egl.eglMakeCurrent(fb->getDisplay(), prevDrawSurf, prevReadSurf, prevContext); - + return true; } bool WindowSurface::resizePbuffer(unsigned int p_width, unsigned int p_height) { - if (m_eglSurface && + if (m_eglSurface && m_pbufWidth == p_width && m_pbufHeight == p_height) { // no need to resize diff --git a/emulator/opengl/host/libs/libOpenglRender/WindowSurface.h b/emulator/opengl/host/libs/libOpenglRender/WindowSurface.h index 1b655c9..e9f1f7d 100644 --- a/emulator/opengl/host/libs/libOpenglRender/WindowSurface.h +++ b/emulator/opengl/host/libs/libOpenglRender/WindowSurface.h @@ -38,13 +38,13 @@ public: EGLSurface getEGLSurface() const { return m_eglSurface; } void setColorBuffer(ColorBufferPtr p_colorBuffer); - void flushColorBuffer(); + bool flushColorBuffer(); void bind(RenderContextPtr p_ctx, SurfaceBindType p_bindType); private: WindowSurface(); - void blitToColorBuffer(); // copy pbuffer content with texload and blit + bool blitToColorBuffer(); // copy pbuffer content with texload and blit bool resizePbuffer(unsigned int p_width, unsigned int p_height); private: diff --git a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp index 8504f7f..c7da37a 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp +++ b/emulator/opengl/shared/OpenglCodecCommon/GLSharedGroup.cpp @@ -16,10 +16,19 @@ #include "GLSharedGroup.h" +/**** KeyedVector utilities ****/ + +template <typename T> +static void clearObjectMap(android::DefaultKeyedVector<GLuint, T>& v) { + for (size_t i = 0; i < v.size(); i++) + delete v.valueAt(i); + v.clear(); +} + /**** BufferData ****/ BufferData::BufferData() : m_size(0) {}; -BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size) +BufferData::BufferData(GLsizeiptr size, void * data) : m_size(size) { void * buffer = NULL; if (size>0) buffer = m_fixedBuffer.alloc(size); @@ -55,7 +64,7 @@ ProgramData::~ProgramData() } void ProgramData::setIndexInfo(GLuint index, GLint base, GLint size, GLenum type) -{ +{ if (index>=m_numIndexes) return; m_Indexes[index].base = base; @@ -87,7 +96,7 @@ GLuint ProgramData::getIndexForLocation(GLint location) for (GLuint i=0;i<m_numIndexes;++i) { GLint dist = location - m_Indexes[i].base; - if (dist >= 0 && + if (dist >= 0 && (minDist < 0 || dist < minDist)) { index = i; minDist = dist; @@ -126,7 +135,7 @@ GLint ProgramData::locationWARHostToApp(GLint hostLoc, GLint arrIndex) GLuint index = getIndexForLocation(hostLoc); if (index<m_numIndexes) { if (arrIndex > 0) { - m_Indexes[index].hostLocsPerElement = + m_Indexes[index].hostLocsPerElement = (hostLoc - m_Indexes[index].base) / arrIndex; } return m_Indexes[index].appBase + arrIndex; @@ -226,12 +235,15 @@ GLSharedGroup::~GLSharedGroup() { m_buffers.clear(); m_programs.clear(); + clearObjectMap(m_buffers); + clearObjectMap(m_programs); + clearObjectMap(m_shaders); } BufferData * GLSharedGroup::getBufferData(GLuint bufferId) { android::AutoMutex _lock(m_lock); - return m_buffers.valueFor(bufferId); + return m_buffers.valueFor(bufferId); } void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data) @@ -243,32 +255,42 @@ void GLSharedGroup::addBufferData(GLuint bufferId, GLsizeiptr size, void * data) void GLSharedGroup::updateBufferData(GLuint bufferId, GLsizeiptr size, void * data) { android::AutoMutex _lock(m_lock); - m_buffers.replaceValueFor(bufferId, new BufferData(size, data)); + ssize_t idx = m_buffers.indexOfKey(bufferId); + if (idx >= 0) { + delete m_buffers.valueAt(idx); + m_buffers.editValueAt(idx) = new BufferData(size, data); + } else { + m_buffers.add(bufferId, new BufferData(size, data)); + } } GLenum GLSharedGroup::subUpdateBufferData(GLuint bufferId, GLintptr offset, GLsizeiptr size, void * data) { android::AutoMutex _lock(m_lock); BufferData * buf = m_buffers.valueFor(bufferId); - if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE; + if ((!buf) || (buf->m_size < offset+size) || (offset < 0) || (size<0)) return GL_INVALID_VALUE; //it's safe to update now memcpy((char*)buf->m_fixedBuffer.ptr() + offset, data, size); - return GL_NO_ERROR; + return GL_NO_ERROR; } void GLSharedGroup::deleteBufferData(GLuint bufferId) { android::AutoMutex _lock(m_lock); - m_buffers.removeItem(bufferId); + ssize_t idx = m_buffers.indexOfKey(bufferId); + if (idx >= 0) { + delete m_buffers.valueAt(idx); + m_buffers.removeItemsAt(idx); + } } void GLSharedGroup::addProgramData(GLuint program) { android::AutoMutex _lock(m_lock); ProgramData *pData = m_programs.valueFor(program); - if (pData) - { + if (pData) + { m_programs.removeItem(program); delete pData; } @@ -290,7 +312,7 @@ bool GLSharedGroup::isProgramInitialized(GLuint program) { android::AutoMutex _lock(m_lock); ProgramData* pData = m_programs.valueFor(program); - if (pData) + if (pData) { return pData->isInitialized(); } @@ -303,7 +325,7 @@ void GLSharedGroup::deleteProgramData(GLuint program) ProgramData *pData = m_programs.valueFor(program); if (pData) delete pData; - m_programs.removeItem(program); + m_programs.removeItem(program); } void GLSharedGroup::attachShader(GLuint program, GLuint shader) @@ -363,7 +385,7 @@ GLenum GLSharedGroup::getProgramUniformType(GLuint program, GLint location) android::AutoMutex _lock(m_lock); ProgramData* pData = m_programs.valueFor(program); GLenum type=0; - if (pData) + if (pData) { type = pData->getTypeForLocation(location); } diff --git a/emulator/qtools/Android.mk b/emulator/qtools/Android.mk index 149390c..8b2c25b 100644 --- a/emulator/qtools/Android.mk +++ b/emulator/qtools/Android.mk @@ -6,7 +6,7 @@ LOCAL_PATH:= $(call my-dir) -common_includes := external/qemu +common_includes := external/qemu/include external/qemu common_cflags := -O0 -g include $(CLEAR_VARS) diff --git a/files/ant/build.xml b/files/ant/build.xml index 1c3f82d..66d7139 100644 --- a/files/ant/build.xml +++ b/files/ant/build.xml @@ -76,6 +76,7 @@ <!-- Renderscript options --> <property name="renderscript.debug.opt.level" value="O0" /> <property name="renderscript.release.opt.level" value="O3" /> + <property name="renderscript.support.mode" value="false" /> <!-- manifest merger default value --> <property name="manifestmerger.enabled" value="false" /> @@ -144,6 +145,8 @@ <property name="out.absolute.dir" location="${out.dir}" /> <property name="out.classes.absolute.dir" location="${out.dir}/classes" /> <property name="out.res.absolute.dir" location="${out.dir}/res" /> + <property name="out.rs.obj.absolute.dir" location="${out.dir}/rsObj" /> + <property name="out.rs.libs.absolute.dir" location="${out.dir}/rsLibs" /> <property name="out.aidl.absolute.dir" location="${out.dir}/aidl" /> <property name="out.dexed.absolute.dir" location="${out.dir}/dexedLibs" /> <property name="out.manifest.abs.file" location="${out.dir}/AndroidManifest.xml" /> @@ -313,6 +316,8 @@ <jarfile refid="project.all.jars.path" /> <nativefolder path="${native.libs.absolute.dir}" /> <nativefolder refid="project.library.native.folder.path" /> + <nativefolder refid="project.rs.support.libs.path" /> + <nativefolder path="${out.rs.libs.absolute.dir}" /> <extra-jars/> </apkbuilder> </sequential> @@ -476,17 +481,11 @@ <!-- Pre build setup --> <target name="-build-setup" depends="-setup"> <!-- find location of build tools --> - <getbuildtools name="android.build.tools.dir" /> + <getbuildtools name="android.build.tools.dir" verbose="${verbose}" /> <property name="aidl" location="${android.build.tools.dir}/aidl${exe}" /> <property name="aapt" location="${android.build.tools.dir}/aapt${exe}" /> <property name="dx" location="${android.build.tools.dir}/dx${bat}" /> - <!-- Renderscript include Path --> - <path id="android.renderscript.include.path"> - <pathelement location="${android.build.tools.dir}/renderscript/include" /> - <pathelement location="${android.build.tools.dir}/renderscript/clang-include" /> - </path> - <!-- read the previous build mode --> <property file="${out.build.prop.file}" /> <!-- if empty the props won't be set, meaning it's a new build. @@ -552,6 +551,8 @@ <mkdir dir="${jar.libs.absolute.dir}" /> <mkdir dir="${out.absolute.dir}" /> <mkdir dir="${out.res.absolute.dir}" /> + <mkdir dir="${out.rs.obj.absolute.dir}" /> + <mkdir dir="${out.rs.libs.absolute.dir}" /> <do-only-if-manifest-hasCode> <mkdir dir="${gen.absolute.dir}" /> <mkdir dir="${out.classes.absolute.dir}" /> @@ -570,6 +571,9 @@ libraryNativeFolderPathOut="project.library.native.folder.path" jarLibraryPathOut="project.all.jars.path" targetApi="${project.target.apilevel}" + renderscriptSupportMode="${renderscript.support.mode}" + buildToolsFolder="${android.build.tools.dir}" + renderscriptSupportLibsOut="project.rs.support.libs.path" verbose="${verbose}" /> <!-- compile the libraries if any --> @@ -661,12 +665,16 @@ <echo level="info">Handling RenderScript files...</echo> <!-- set the rs target prop in case it hasn't been set. --> <property name="renderscript.target" value="${project.minSdkVersion}" /> - <renderscript buildToolsRoot="${android.build.tools.dir}" - includePathRefId="android.renderscript.include.path" + <renderscript + buildToolsRoot="${android.build.tools.dir}" genFolder="${gen.absolute.dir}" - resFolder="${out.res.absolute.dir}/raw" + resFolder="${out.res.absolute.dir}" + rsObjFolder="${out.rs.obj.absolute.dir}" + libsFolder="${out.rs.libs.absolute.dir}" targetApi="${renderscript.target}" optLevel="${renderscript.opt.level}" + supportMode="${renderscript.support.mode}" + binFolder="${out.absolute.dir}" buildType="${build.is.packaging.debug}" previousBuildType="${build.last.is.packaging.debug}"> <source path="${source.absolute.dir}"/> diff --git a/files/tools_source.properties b/files/tools_source.properties index 2e8aa8a..7e6337e 100644 --- a/files/tools_source.properties +++ b/files/tools_source.properties @@ -1,3 +1,3 @@ Pkg.UserSrc=false -Pkg.Revision=22.0.1 -Platform.MinPlatformToolsRev=16 +Pkg.Revision=22.3 +Platform.MinPlatformToolsRev=18 diff --git a/find_java/find_java.bat b/find_java/find_java.bat index 6355f23..e7bc590 100755 --- a/find_java/find_java.bat +++ b/find_java/find_java.bat @@ -23,14 +23,14 @@ rem http://technet.microsoft.com/en-us/library/bb490890.aspx rem Check we have a valid Java.exe in the path. The return code will
rem be 0 if the command worked or 1 if the exec failed (program not found).
-for /f %%a in ('%~dps0\find_java.exe -s') do set java_exe=%%a
+for /f "delims=" %%a in ('"%~dps0\find_java.exe" -s') do set java_exe=%%a
if not defined java_exe goto :CheckFailed
:SearchJavaW
rem Check if we can find a javaw.exe at the same location than java.exe.
rem If that doesn't work, just fall back on the java.exe we just found.
-for /f %%a in ('%~dps0\find_java.exe -s -w') do set javaw_exe=%%a
-if not exist %javaw_exe% set javaw_exe=%java_exe%
+for /f "delims=" %%a in ('"%~dps0\find_java.exe" -s -w') do set javaw_exe=%%a
+if not exist "%javaw_exe%" set javaw_exe=%java_exe%
goto :EOF
diff --git a/hierarchyviewer/etc/hierarchyviewer1.bat b/hierarchyviewer/etc/hierarchyviewer1.bat index 3f8c416..b4da06a 100755 --- a/hierarchyviewer/etc/hierarchyviewer1.bat +++ b/hierarchyviewer/etc/hierarchyviewer1.bat @@ -30,17 +30,17 @@ call lib\find_java.bat if not defined java_exe goto :EOF set jarfile=hierarchyviewer.jar -set frameworkdir= +set frameworkdir=. set libdir= -if exist %frameworkdir%%jarfile% goto JarFileOk - set frameworkdir=lib\ +if exist %frameworkdir%\%jarfile% goto JarFileOk + set frameworkdir=lib -if exist %frameworkdir%%jarfile% goto JarFileOk - set frameworkdir=..\framework\ +if exist %frameworkdir%\%jarfile% goto JarFileOk + set frameworkdir=..\framework :JarFileOk -set jarpath=%frameworkdir%%jarfile% +set jarpath=%frameworkdir%\%jarfile% -call %java_exe% -Xmx512m -Djava.ext.dirs=%frameworkdir% -Dhierarchyviewer.adb= -jar %jarpath% %* +call "%java_exe%" -Xmx512m "-Djava.ext.dirs=%frameworkdir%" -Dhierarchyviewer.adb= -jar %jarpath% %* diff --git a/monitor/Android.mk b/monitor/Android.mk index 60e4966..8e3f000 100644 --- a/monitor/Android.mk +++ b/monitor/Android.mk @@ -1,5 +1,13 @@ # Copyright 2012 The Android Open Source Project +# Temporarily disable building monitor +# The current mechanism for building monitor using PDE build does +# not work with Java7 on Macs. So building monitor is temporarily +# disabled until we figure out how to build monitor using Tycho +# and incorporate it into this build script. +# See b/8992787 +ifeq (0,1) + # Expose the Monitor RCP only for the SDK builds. ifneq (,$(is_sdk_build)$(filter sdk sdk_x86 sdk_mips,$(TARGET_PRODUCT))) @@ -60,3 +68,4 @@ $(LOCAL_BUILT_MODULE) : $(TOPDIR)sdk/monitor/monitor \ $(hide)$(ACP) -fp $(V) $(TOPDIR)sdk/monitor/monitor $@ endif +endif diff --git a/monitor/monitor.bat b/monitor/monitor.bat index 9bcc4e0..aab18ae 100755 --- a/monitor/monitor.bat +++ b/monitor/monitor.bat @@ -26,7 +26,7 @@ call lib\find_java.bat if not defined java_exe goto :EOF
:QueryArch
-for /f %%a in ('%java_exe% -jar lib\archquery.jar') do set vmarch=%%a
+for /f "delims=" %%a in ('"%java_exe%" -jar lib\archquery.jar') do set vmarch=%%a
start lib\monitor-%vmarch%\monitor
diff --git a/testapps/basicJar/build.xml b/testapps/basicJar/build.xml index d7f73e9..ebe77ff 100644 --- a/testapps/basicJar/build.xml +++ b/testapps/basicJar/build.xml @@ -3,7 +3,7 @@ <target name="compile"> <mkdir dir="${basedir}/bin" /> <mkdir dir="${basedir}/bin/classes" /> - <javac encoding="ascii" target="1.5" debug="true" extdirs="" + <javac encoding="ascii" target="1.5" source="1.5" debug="true" extdirs="" srcdir="src" destdir="${basedir}/bin/classes" /> <jar destfile="${basedir}/bin/${ant.project.name}.jar"> <fileset dir="${basedir}/bin/classes" /> @@ -13,4 +13,4 @@ <target name="clean"> <delete dir="bin" /> </target> -</project>
\ No newline at end of file +</project> diff --git a/testapps/basicJar2/build.xml b/testapps/basicJar2/build.xml index 1c02cfd..a5b0657 100644 --- a/testapps/basicJar2/build.xml +++ b/testapps/basicJar2/build.xml @@ -3,7 +3,7 @@ <target name="compile"> <mkdir dir="${basedir}/bin" /> <mkdir dir="${basedir}/bin/classes" /> - <javac encoding="ascii" target="1.5" debug="true" extdirs="" + <javac encoding="ascii" target="1.5" source="1.5" debug="true" extdirs="" srcdir="src" destdir="${basedir}/bin/classes" /> <jar destfile="${basedir}/bin/${ant.project.name}.jar"> <fileset dir="${basedir}/bin/classes" /> @@ -13,4 +13,4 @@ <target name="clean"> <delete dir="bin" /> </target> -</project>
\ No newline at end of file +</project> diff --git a/testapps/basicJar3/build.xml b/testapps/basicJar3/build.xml index 41f7ee8..208501f 100644 --- a/testapps/basicJar3/build.xml +++ b/testapps/basicJar3/build.xml @@ -3,7 +3,7 @@ <target name="compile"> <mkdir dir="${basedir}/bin" /> <mkdir dir="${basedir}/bin/classes" /> - <javac encoding="ascii" target="1.5" debug="true" extdirs="" + <javac encoding="ascii" target="1.5" source="1.5" debug="true" extdirs="" srcdir="src" destdir="${basedir}/bin/classes" /> <jar destfile="${basedir}/bin/${ant.project.name}.jar"> <fileset dir="${basedir}/bin/classes" /> @@ -13,4 +13,4 @@ <target name="clean"> <delete dir="bin" /> </target> -</project>
\ No newline at end of file +</project> |