Merge change 3202 into donut

* changes:
  Make runtest wait for instrumentation install before running test.
diff --git a/build/sdk-darwin-x86.atree b/build/sdk-darwin-x86.atree
index 13ed592..19be137 100644
--- a/build/sdk-darwin-x86.atree
+++ b/build/sdk-darwin-x86.atree
@@ -2,12 +2,8 @@
 #
 
 # swt
-lib/libswt-carbon-3236.jnilib tools/lib/libswt-carbon-3236.jnilib
-lib/libswt-pi-carbon-3236.jnilib tools/lib/libswt-pi-carbon-3236.jnilib
-framework/swt.jar tools/lib/swt.jar
-framework/org.eclipse.core.commands_3.2.0.I20060605-1400.jar tools/lib/org.eclipse.core.commands_3.2.0.I20060605-1400.jar
-framework/org.eclipse.equinox.common_3.2.0.v20060603.jar tools/lib/org.eclipse.equinox.common_3.2.0.v20060603.jar
-framework/org.eclipse.jface_3.2.0.I20060605-1400.jar tools/lib/org.eclipse.jface_3.2.0.I20060605-1400.jar
+prebuilt/darwin-x86/swt/swt.jar tools/lib/x86/swt.jar
+
 
 # JetCreator (only available on mac/windows)
 external/sonivox/jet_tools/JetCreator tools/Jet/JetCreator
diff --git a/build/sdk-linux-x86.atree b/build/sdk-linux-x86.atree
index 1324f55..c580353 100644
--- a/build/sdk-linux-x86.atree
+++ b/build/sdk-linux-x86.atree
@@ -2,11 +2,5 @@
 #
 
 # swt
-lib/libswt-atk-gtk-3236.so tools/lib/libswt-atk-gtk-3236.so
-lib/libswt-gtk-3236.so tools/lib/libswt-gtk-3236.so
-lib/libswt-pi-gtk-3236.so tools/lib/libswt-pi-gtk-3236.so
-lib/libswt-cairo-gtk-3236.so tools/lib/libswt-cairo-gtk-3236.so
-framework/swt.jar tools/lib/swt.jar
-framework/org.eclipse.core.commands_3.2.0.I20060605-1400.jar tools/lib/org.eclipse.core.commands_3.2.0.I20060605-1400.jar
-framework/org.eclipse.equinox.common_3.2.0.v20060603.jar tools/lib/org.eclipse.equinox.common_3.2.0.v20060603.jar
-framework/org.eclipse.jface_3.2.0.I20060605-1400.jar tools/lib/org.eclipse.jface_3.2.0.I20060605-1400.jar
+prebuilt/linux-x86/swt/swt.jar tools/lib/x86/swt.jar
+prebuilt/linux-x86_64/swt/swt.jar tools/lib/x86_64/swt.jar
\ No newline at end of file
diff --git a/build/sdk.atree b/build/sdk.atree
index bd5fabe..fe2a17f 100644
--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -30,6 +30,12 @@
 # the uper-jar file that apps link against
 out/target/common/obj/PACKAGING/android_jar_intermediates/android.jar platforms/${PLATFORM_NAME}/android.jar
 
+# eclipse files for SWT
+framework/org.eclipse.core.commands_3.4.0.I20080509-2000.jar tools/lib/org.eclipse.core.commands_3.4.0.I20080509-2000.jar
+framework/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar tools/lib/org.eclipse.equinox.common_3.4.0.v20080421-2006.jar
+framework/org.eclipse.jface_3.4.2.M20090107-0800.jar tools/lib/org.eclipse.jface_3.4.2.M20090107-0800.jar
+
+
 sdk/sdk-build.prop platforms/${PLATFORM_NAME}/build.prop
 development/tools/scripts/plugin.prop tools/lib/plugin.prop
 
@@ -90,6 +96,9 @@
 framework/jfreechart-1.0.9.jar tools/lib/jfreechart-1.0.9.jar
 framework/jfreechart-1.0.9-swt.jar tools/lib/jfreechart-1.0.9-swt.jar
 
+# archquery to test VM architecture
+framework/archquery.jar tools/lib/archquery.jar
+
 # ddms
 bin/ddms tools/ddms
 framework/ddms.jar tools/lib/ddms.jar
diff --git a/build/tools/make_windows_sdk.sh b/build/tools/make_windows_sdk.sh
index 0ce9caa..b5f5c1d 100755
--- a/build/tools/make_windows_sdk.sh
+++ b/build/tools/make_windows_sdk.sh
@@ -126,14 +126,14 @@
     LIB="$TEMP_SDK_DIR/tools/lib"
     rm -v "$TOOLS"/{adb,android,apkbuilder,ddms,dmtracedump,draw9patch,emulator}
     rm -v "$TOOLS"/{hierarchyviewer,hprof-conv,mksdcard,sqlite3,traceview}
-    rm -vf "$LIB"/*.so "$LIB"/*.jnilib
-    rm -v  "$PLATFORM_TOOLS"/{aapt,aidl,dx,dexdump}
-
+    rm -v "$LIB"/*/swt.jar
+    rm -v "$PLATFORM_TOOLS"/{aapt,aidl,dx,dexdump}
 
     # Copy all the new stuff in tools
     # Note: some tools are first copied here and then moved in platforms/<name>/tools/
     cp -v out/host/windows-x86/bin/*.{exe,dll} "$TOOLS"
-    cp -v prebuilt/windows/swt/*.{jar,dll}     "$LIB"
+    cp -v prebuilt/windows/swt/swt.jar         "$LIB"/x86
+    cp -v prebuilt/windows-x86_64/swt/swt.jar  "$LIB"/x86_64
 
     # If you want the emulator NOTICE in the tools dir, uncomment the following line:
     # cp -v external/qemu/NOTICE "$TOOLS"/emulator_NOTICE.txt
@@ -148,7 +148,7 @@
     cp -v development/tools/hierarchyviewer/etc/hierarchyviewer.bat "$TOOLS"
     cp -v development/tools/draw9patch/etc/draw9patch.bat           "$TOOLS"
     cp -v development/tools/sdkmanager/app/etc/android.bat          "$TOOLS"
-    
+
     # Put the JetCreator tools, content and docs (not available in the linux SDK)
     JET="$TOOLS/Jet"
     JETCREATOR="$JET/JetCreator"
diff --git a/testrunner/run_command.py b/testrunner/run_command.py
index ead80f1..8cf385b 100755
--- a/testrunner/run_command.py
+++ b/testrunner/run_command.py
@@ -146,10 +146,16 @@
     return subproc.returncode
   else:
     # Need the full path to valgrind to avoid other versions on the system.
-    subproc = subprocess.Popen(["/usr/bin/valgrind", "-q", full_path],
+    subproc = subprocess.Popen(["/usr/bin/valgrind", "--tool=memcheck",
+                                "--leak-check=yes", "-q", full_path],
                                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
-    subproc.wait()
-    return subproc.returncode
+    # Cannot rely on the retcode of valgrind. Instead look for an empty output.
+    valgrind_out = subproc.communicate()[0].strip()
+    if valgrind_out:
+      print valgrind_out
+      return 1
+    else:
+      return 0
 
 
 def HasValgrind():
diff --git a/tools/archquery/.classpath b/tools/archquery/.classpath
new file mode 100644
index 0000000..fb50116
--- /dev/null
+++ b/tools/archquery/.classpath
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/tools/archquery/.gitignore b/tools/archquery/.gitignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/tools/archquery/.gitignore
@@ -0,0 +1 @@
+bin
diff --git a/tools/archquery/.project b/tools/archquery/.project
new file mode 100644
index 0000000..9886091
--- /dev/null
+++ b/tools/archquery/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>archquery</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/tools/archquery/Android.mk b/tools/archquery/Android.mk
new file mode 100644
index 0000000..53cad46
--- /dev/null
+++ b/tools/archquery/Android.mk
@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+ARCHQUERY_LOCAL_DIR := $(call my-dir)
+include $(ARCHQUERY_LOCAL_DIR)/src/Android.mk
diff --git a/tools/archquery/etc/manifest.txt b/tools/archquery/etc/manifest.txt
new file mode 100644
index 0000000..a362e88
--- /dev/null
+++ b/tools/archquery/etc/manifest.txt
@@ -0,0 +1 @@
+Main-Class: com.android.archquery.Main
diff --git a/tools/archquery/src/Android.mk b/tools/archquery/src/Android.mk
new file mode 100644
index 0000000..980f002
--- /dev/null
+++ b/tools/archquery/src/Android.mk
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2009 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_JAR_MANIFEST := ../etc/manifest.txt
+LOCAL_JAVA_LIBRARIES := \
+
+LOCAL_MODULE := archquery
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/archquery/src/com/android/archquery/Main.java b/tools/archquery/src/com/android/archquery/Main.java
new file mode 100644
index 0000000..5e65ff2
--- /dev/null
+++ b/tools/archquery/src/com/android/archquery/Main.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.archquery;
+
+/**
+ * Java command line tool to return the CPU architecture of the host java VM.
+ *
+ * The goal is to be able to launch SWT based applications (DDMS, Traceview, Android) on any
+ * type of OS.
+ *
+ * Because a 64 bit OS can run a 32 bit Virtual Machine, we need to query the VM itself to know
+ * whether it's 32 or 64 bit to detect which swt.jar it should use (it contains native libraries).
+ * Simply querying the OS is not enough.
+ *
+ * The other problem is that once a VM is launched it is impossible to change its classpath to
+ * point the VM to the correct version of swt.jar.
+ *
+ * The solution is this small command line tool, running in the VM, and returning the value of
+ * the 'os.arch' property. Based on the returned value, the script launching the SWT based
+ * applications will configure the Java VM with the path to the correct swt.jar
+ *
+ * Because different VMs return different values for 32 and 64 bit version of x86 CPUs, the program
+ * handles all the possible values and normalize the returned value.
+ *
+ * At this time, the normalized values are:
+ * x86:    32 bit x86
+ * x86_64: 64 bit x86
+ * ppc:    PowerPC (WARNING: the SDK doesn't actually support this architecture).
+ *
+ *
+ */
+public final class Main {
+    public static void main(String[] args) {
+        // Values listed from http://lopica.sourceforge.net/os.html
+        String arch = System.getProperty("os.arch");
+
+        if (arch.equalsIgnoreCase("x86_64") || arch.equalsIgnoreCase("amd64")) {
+            System.out.print("x86_64");
+
+        } else if (arch.equalsIgnoreCase("x86")
+                || arch.equalsIgnoreCase("i386")
+                || arch.equalsIgnoreCase("i686")) {
+            System.out.print("x86");
+
+        } else if (arch.equalsIgnoreCase("ppc") || arch.equalsIgnoreCase("PowerPC")) {
+            System.out.print("ppc");
+        } else {
+            System.out.print(arch);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tools/ddms/app/etc/ddms b/tools/ddms/app/etc/ddms
index c63930b..e9ee6a0 100755
--- a/tools/ddms/app/etc/ddms
+++ b/tools/ddms/app/etc/ddms
@@ -67,29 +67,6 @@
     os_opts="-XstartOnFirstThread"
     #because Java 1.6 is 64 bits only and SWT doesn't support this, we force the usage of java 1.5
     java_cmd="/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Commands/java"
-elif [[ `uname -s` = 'Linux' ]]; then
-    # We need a 32-bit Java on Linux, because our JNI libraries are 32-bit.
-    java_cmd=`which java`
-
-    if [ -x "$java_cmd" ]; then
-        if [[ ! `file -L "$java_cmd"` =~ "ELF 32-bit LSB executable" ]]; then
-            java_cmd=""
-        fi
-    fi
-
-    if [ ! -x "$java_cmd" ]; then
-        # The default JVM is not suitable.
-        # See if we can find a particular known-good JVM
-        java_cmd="/usr/lib/jvm/ia32-java-6-sun/jre/bin/java"
-        if [ ! -x "$java_cmd" ]; then
-            PREFIX=`basename "$prog"`
-            echo "$PREFIX: The default Java VM is not an ELF 32-bit LSB executable."
-            echo "$PREFIX: Please do one of the following:"
-            echo "$PREFIX: 1) Arrange for the default Java VM to be an ELF 32-bit LSB executable."
-            echo "$PREFIX: 2) Install the ia32-sun-java6-bin package."
-            exit 1
-        fi
-    fi
 else
     os_opts=
     java_cmd="java"
@@ -102,6 +79,32 @@
     jarpath="$frameworkdir/$jarfile"
 fi
 
+# Figure out the path to the swt.jar for the current architecture.
+# if ANDROID_SWT is defined, then just use this.
+# else, if running in the Android source tree, then look for the correct swt folder in prebuilt
+# else, look for the correct swt folder in the SDK under tools/lib/
+swtpath=""
+if [ -n "$ANDROID_SWT" ]; then
+    swtpath="$ANDROID_SWT"
+else
+    vmarch=`java -jar "${frameworkdir}"/archquery.jar`
+    if [ -n "$ANDROID_BUILD_TOP" ]; then
+        osname=`uname -s | tr A-Z a-z`
+        swtpath="${ANDROID_BUILD_TOP}/prebuilt/${osname}-${vmarch}/swt"
+    else
+        swtpath="${frameworkdir}/${vmarch}"
+    fi
+fi
+
+# Combine the swtpath and the framework dir path.
+if [ -d "$swtpath" ]; then
+    frameworkdir="${swtpath}:${frameworkdir}"
+else
+    echo "SWT folder '${swtpath}' does not exist."
+    echo "Please export ANDROID_SWT to point to the folder containing swt.jar for your platform."
+    exit 1
+fi
+
 # need to use "java.ext.dirs" because "-jar" causes classpath to be ignored
 # might need more memory, e.g. -Xmx128M
-exec "$java_cmd" -Xmx256M $os_opts $java_debug -Djava.ext.dirs="$frameworkdir" -Djava.library.path="$libdir" -Dcom.android.ddms.bindir="$progdir" -jar "$jarpath" "$@"
+exec "$java_cmd" -Xmx256M $os_opts $java_debug -Djava.ext.dirs="$frameworkdir" -Dcom.android.ddms.bindir="$progdir" -jar "$jarpath" "$@"
diff --git a/tools/ddms/app/etc/ddms.bat b/tools/ddms/app/etc/ddms.bat
index 5da9fb5..ffe536d 100755
--- a/tools/ddms/app/etc/ddms.bat
+++ b/tools/ddms/app/etc/ddms.bat
@@ -26,15 +26,12 @@
 
 set jarfile=ddms.jar
 set frameworkdir=
-set libdir=
 
 if exist %frameworkdir%%jarfile% goto JarFileOk
     set frameworkdir=lib\
-    set libdir=lib\
 
 if exist %frameworkdir%%jarfile% goto JarFileOk
     set frameworkdir=..\framework\
-    set libdir=..\lib\
 
 :JarFileOk
 
@@ -45,4 +42,23 @@
 
 set jarpath=%frameworkdir%%jarfile%
 
-call java %java_debug% -Djava.ext.dirs=%frameworkdir% -Djava.library.path=%libdir% -Dcom.android.ddms.bindir= -jar %jarpath% %*
+if not defined ANDROID_SWT goto QueryArch
+    set swt_path=%ANDROID_SWT%
+    goto SwtDone
+
+:QueryArch
+
+    for /f %%a in ('java -jar %frameworkdir%archquery.jar') do set swt_path=%frameworkdir%%%a
+
+:SwtDone
+
+if exist %swt_path% goto SetPath
+    echo SWT folder '%swt_path%' does not exist.
+    echo Please set ANDROID_SWT to point to the folder containing swt.jar for your platform.
+    exit /B
+
+:SetPath
+set javaextdirs=%swt_path%;%frameworkdir%
+
+call java %java_debug% -Djava.ext.dirs=%javaextdirs% -Dcom.android.ddms.bindir= -jar %jarpath% %*
+
diff --git a/tools/ddms/app/src/Android.mk b/tools/ddms/app/src/Android.mk
index a013fa6..c62b678 100644
--- a/tools/ddms/app/src/Android.mk
+++ b/tools/ddms/app/src/Android.mk
@@ -13,9 +13,9 @@
 	ddmlib \
 	ddmuilib \
 	swt \
-	org.eclipse.jface_3.2.0.I20060605-1400 \
-	org.eclipse.equinox.common_3.2.0.v20060603 \
-	org.eclipse.core.commands_3.2.0.I20060605-1400
+	org.eclipse.jface_3.4.2.M20090107-0800 \
+	org.eclipse.equinox.common_3.4.0.v20080421-2006 \
+	org.eclipse.core.commands_3.4.0.I20080509-2000
 LOCAL_MODULE := ddms
 
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/ddms/libs/ddmuilib/src/Android.mk b/tools/ddms/libs/ddmuilib/src/Android.mk
index acbda44..68ceac1 100644
--- a/tools/ddms/libs/ddmuilib/src/Android.mk
+++ b/tools/ddms/libs/ddmuilib/src/Android.mk
@@ -9,9 +9,9 @@
 LOCAL_JAVA_LIBRARIES := \
 	ddmlib \
 	swt \
-	org.eclipse.jface_3.2.0.I20060605-1400 \
-	org.eclipse.equinox.common_3.2.0.v20060603 \
-	org.eclipse.core.commands_3.2.0.I20060605-1400 \
+	org.eclipse.jface_3.4.2.M20090107-0800 \
+	org.eclipse.equinox.common_3.4.0.v20080421-2006 \
+	org.eclipse.core.commands_3.4.0.I20080509-2000 \
 	jcommon-1.0.12 \
 	jfreechart-1.0.9 \
 	jfreechart-1.0.9-swt
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 0ac3bb9..b4289a6 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -987,9 +987,9 @@
 
                     return Status.OK_STATUS;
                 } catch (Throwable t) {
-                    log(t, "pingUsageServer failed"); //$NON-NLS-1$
+                    log(t, "pingUsageServer failed");       //$NON-NLS-1$
                     return new Status(IStatus.ERROR, PLUGIN_ID,
-                            "pingUsageServer failed", t);
+                            "pingUsageServer failed", t);    //$NON-NLS-1$
                 }
             }
         };
@@ -1096,6 +1096,11 @@
                             }
                         }
                     });
+                } catch (Throwable t) {
+                    log(t, "Unknown exception in parseSdkContent.");    //$NON-NLS-1$
+                    return new Status(IStatus.ERROR, PLUGIN_ID,
+                            "parseSdkContent failed", t);               //$NON-NLS-1$
+
                 } finally {
                     mSdkIsLoading = false;
                     if (monitor != null) {
diff --git a/tools/screenshot/.gitignore b/tools/screenshot/.gitignore
new file mode 100644
index 0000000..ba077a4
--- /dev/null
+++ b/tools/screenshot/.gitignore
@@ -0,0 +1 @@
+bin
diff --git a/tools/sdkmanager/app/etc/android b/tools/sdkmanager/app/etc/android
index af4042b..ee21b0e 100755
--- a/tools/sdkmanager/app/etc/android
+++ b/tools/sdkmanager/app/etc/android
@@ -79,6 +79,32 @@
     jarpath="$frameworkdir/$jarfile"
 fi
 
+# Figure out the path to the swt.jar for the current architecture.
+# if ANDROID_SWT is defined, then just use this.
+# else, if running in the Android source tree, then look for the correct swt folder in prebuilt
+# else, look for the correct swt folder in the SDK under tools/lib/
+swtpath=""
+if [ -n "$ANDROID_SWT" ]; then
+    swtpath="$ANDROID_SWT"
+else
+    vmarch=`java -jar "${frameworkdir}"/archquery.jar`
+    if [ -n "$ANDROID_BUILD_TOP" ]; then
+        osname=`uname -s | tr A-Z a-z`
+        swtpath="${ANDROID_BUILD_TOP}/prebuilt/${osname}-${vmarch}/swt"
+    else
+        swtpath="${frameworkdir}/${vmarch}"
+    fi
+fi
+
+# Combine the swtpath and the framework dir path.
+if [ -d "$swtpath" ]; then
+    frameworkdir="${swtpath}:${frameworkdir}"
+else
+    echo "SWT folder '${swtpath}' does not exist."
+    echo "Please export ANDROID_SWT to point to the folder containing swt.jar for your platform."
+    exit 1
+fi
+
 # need to use "java.ext.dirs" because "-jar" causes classpath to be ignored
 # might need more memory, e.g. -Xmx128M
-exec "$java_cmd" -Xmx256M $os_opts $java_debug -Djava.ext.dirs="$frameworkdir" -Djava.library.path="$libdir" -Dcom.android.sdkmanager.toolsdir="$progdir" -jar "$jarpath" "$@"
+exec "$java_cmd" -Xmx256M $os_opts $java_debug -Djava.ext.dirs="$frameworkdir" -Dcom.android.sdkmanager.toolsdir="$progdir" -jar "$jarpath" "$@"
diff --git a/tools/sdkmanager/app/etc/android.bat b/tools/sdkmanager/app/etc/android.bat
index de950ed..b41105c 100755
--- a/tools/sdkmanager/app/etc/android.bat
+++ b/tools/sdkmanager/app/etc/android.bat
@@ -29,23 +29,33 @@
 
 set jarfile=sdkmanager.jar
 set frameworkdir=
-set libdir=
 
 if exist %frameworkdir%%jarfile% goto JarFileOk
     set frameworkdir=lib\
-    set libdir=lib\
 
 if exist %frameworkdir%%jarfile% goto JarFileOk
     set frameworkdir=..\framework\
-    set libdir=..\lib\
 
 :JarFileOk
 
-if debug NEQ "%1" goto NoDebug
-    set java_debug=-agentlib:jdwp=transport=dt_socket,server=y,address=8050,suspend=y
-    shift 1
-:NoDebug
-
 set jarpath=%frameworkdir%%jarfile%
 
-call java %java_debug% -Djava.ext.dirs=%frameworkdir% -Djava.library.path=%libdir% -Dcom.android.sdkmanager.toolsdir= -Dcom.android.sdkmanager.workdir="%workdir%" -jar %jarpath% %*
+if not defined ANDROID_SWT goto QueryArch
+    set swt_path=%ANDROID_SWT%
+    goto SwtDone
+
+:QueryArch
+
+    for /f %%a in ('java -jar %frameworkdir%archquery.jar') do set swt_path=%frameworkdir%%%a
+
+:SwtDone
+
+if exist %swt_path% goto SetPath
+    echo SWT folder '%swt_path%' does not exist.
+    echo Please set ANDROID_SWT to point to the folder containing swt.jar for your platform.
+    exit /B
+
+:SetPath
+set javaextdirs=%swt_path%;%frameworkdir%
+
+call java -Djava.ext.dirs=%javaextdirs% -Dcom.android.sdkmanager.toolsdir= -Dcom.android.sdkmanager.workdir="%workdir%" -jar %jarpath% %*
diff --git a/tools/sdkmanager/app/src/Android.mk b/tools/sdkmanager/app/src/Android.mk
index 6346349..b67bf6a 100644
--- a/tools/sdkmanager/app/src/Android.mk
+++ b/tools/sdkmanager/app/src/Android.mk
@@ -11,9 +11,10 @@
 	sdklib \
 	sdkuilib \
 	swt \
-	org.eclipse.jface_3.2.0.I20060605-1400 \
-	org.eclipse.equinox.common_3.2.0.v20060603 \
-	org.eclipse.core.commands_3.2.0.I20060605-1400
+	org.eclipse.jface_3.4.2.M20090107-0800 \
+	org.eclipse.equinox.common_3.4.0.v20080421-2006 \
+	org.eclipse.core.commands_3.4.0.I20080509-2000
+
 LOCAL_MODULE := sdkmanager
 
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskMonitor.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskMonitor.java
index 05c982d..c8f7c06 100755
--- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskMonitor.java
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ITaskMonitor.java
@@ -55,9 +55,15 @@
     public void incProgress(int delta);

 

     /**

+     * Returns the current value of the progress bar,

+     * between 0 and up to {@link #setProgressMax(int)} - 1.

+     */

+    public int getProgress();

+

+    /**

      * Returns true if the user requested to cancel the operation.

      * It is up to the task thread to pool this and exit as soon

      * as possible.

      */

-    public boolean cancelRequested();

+    public boolean isCancelRequested();

 }

diff --git a/tools/sdkmanager/libs/sdkuilib/src/Android.mk b/tools/sdkmanager/libs/sdkuilib/src/Android.mk
index 2d3c774..357a60d 100644
--- a/tools/sdkmanager/libs/sdkuilib/src/Android.mk
+++ b/tools/sdkmanager/libs/sdkuilib/src/Android.mk
@@ -11,9 +11,9 @@
 LOCAL_JAVA_LIBRARIES := \
 	sdklib \
 	swt \
-	org.eclipse.jface_3.2.0.I20060605-1400 \
-	org.eclipse.equinox.common_3.2.0.v20060603 \
-	org.eclipse.core.commands_3.2.0.I20060605-1400
+	org.eclipse.jface_3.4.2.M20090107-0800 \
+	org.eclipse.equinox.common_3.4.0.v20080421-2006 \
+	org.eclipse.core.commands_3.4.0.I20080509-2000
 	
 LOCAL_MODULE := sdkuilib
 
diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalPackagesPage.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalPackagesPage.java
index 6e9cef8..abc729e 100755
--- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalPackagesPage.java
+++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalPackagesPage.java
@@ -232,7 +232,7 @@
                 monitor.setProgressMax(100);

                 int n = 0;

                 int d = 1;

-                while(!monitor.cancelRequested()) {

+                while(!monitor.isCancelRequested()) {

                     monitor.incProgress(d);

                     n += d;

                     if (n == 0 || n == 100) d = -d;

diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressDialog.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressDialog.java
index b1f5da7..a5cb86f 100755
--- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressDialog.java
+++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressDialog.java
@@ -148,7 +148,7 @@
         });

 

         mResultText = new Text(mRootComposite,

-                SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL | SWT.MULTI);

+                SWT.BORDER | SWT.READ_ONLY | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);

         mResultText.setEditable(true);

         mResultText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));

     }

@@ -286,7 +286,15 @@
                 public void run() {

                     if (!mResultText.isDisposed()) {

                         mResultText.setVisible(true);

-                        mResultText.setText(String.format(resultFormat, args));

+                        String newText = String.format(resultFormat, args);

+                        String lastText = mResultText.getText();

+                        if (lastText != null &&

+                                lastText.length() > 0 &&

+                                !lastText.endsWith("\n") &&

+                                !newText.startsWith("\n")) {

+                            mResultText.append("\n");

+                        }

+                        mResultText.append(newText);

                     }

                 }

             });

@@ -328,6 +336,27 @@
     }

 

     /**

+     * Returns the current value of the progress bar,

+     * between 0 and up to {@link #setProgressMax(int)} - 1.

+     * This method can be invoked from a non-UI thread.

+     */

+    public int getProgress() {

+        final int[] result = new int[] { 0 };

+

+        if (!mDialogShell.isDisposed()) {

+            mDialogShell.getDisplay().syncExec(new Runnable() {

+                public void run() {

+                    if (!mProgressBar.isDisposed()) {

+                        result[0] = mProgressBar.getSelection();

+                    }

+                }

+            });

+        }

+

+        return result[0];

+    }

+

+    /**

      * Starts the thread that runs the task.

      * This is deferred till the UI is created.

      */

diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTask.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTask.java
index b2599ef..709cce0 100755
--- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTask.java
+++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/ProgressTask.java
@@ -81,10 +81,20 @@
     }

 

     /**

+     * Returns the current value of the progress bar,

+     * between 0 and up to {@link #setProgressMax(int)} - 1.

+     *

+     * This method can be invoked from a non-UI thread.

+     */

+    public int getProgress() {

+        return mDialog.getProgress();

+    }

+

+    /**

      * Returns true if the "Cancel" button was selected.

      * It is up to the task thread to pool this and exit.

      */

-    public boolean cancelRequested() {

+    public boolean isCancelRequested() {

         return mDialog.isCancelRequested();

     }

 

diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java
index a7223b5..ddf53f0 100755
--- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java
+++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/UpdaterWindowImpl.java
@@ -43,6 +43,7 @@
 import org.eclipse.swt.widgets.Shell;

 

 import java.io.File;

+import java.io.FileInputStream;

 import java.io.FileOutputStream;

 import java.io.IOException;

 import java.io.InputStream;

@@ -51,13 +52,15 @@
 import java.security.MessageDigest;

 import java.util.ArrayList;

 import java.util.Collection;

+import java.util.zip.ZipEntry;

+import java.util.zip.ZipInputStream;

 

 /**

  * This is the private implementation of the UpdateWindow.

  */

 public class UpdaterWindowImpl {

 

-    private static final int NUM_FETCH_URL_MONITOR_INC = 100;

+    private static final int NUM_MONITOR_INC = 100;

 

     /** Internal data shared between the window and its pages. */

     private final UpdaterData mUpdaterData = new UpdaterData();

@@ -338,49 +341,66 @@
      * @param archives The archives to install. Incompatible ones will be skipped.

      */

     public void installArchives(final Collection<Archive> archives) {

+

+        // TODO filter the archive list to: a/ display a list of what is going to be installed,

+        // b/ display licenses and c/ check that the selected packages are actually upgrades

+        // or ask user to confirm downgrades. All this should be done in a separate class+window

+        // which will then call this method with the final list.

+

         // TODO move most parts to SdkLib, maybe as part of Archive, making archives self-installing.

         mTaskFactory.start("Installing Archives", new ITask() {

             public void run(ITaskMonitor monitor) {

 

-                monitor.setProgressMax(archives.size() * (NUM_FETCH_URL_MONITOR_INC + 10));

+                final int progressPerArchive = 2 * NUM_MONITOR_INC + 10;

+                monitor.setProgressMax(archives.size() * progressPerArchive);

                 monitor.setDescription("Preparing to install archives");

 

-                int num_installed = 0;

+                int numInstalled = 0;

                 for (Archive archive : archives) {

 

-                    if (!archive.isCompatible()) {

-                        monitor.setResult("Skipping incompatible archive: %1$s",

-                                archive.getParentPackage().getShortDescription());

-                        monitor.incProgress(NUM_FETCH_URL_MONITOR_INC + 10);

-                        continue;

-                    }

-

+                    int nextProgress = monitor.getProgress() + progressPerArchive;

                     File archiveFile = null;

                     try {

+                        if (monitor.isCancelRequested()) {

+                            break;

+                        }

+

+                        String name = archive.getParentPackage().getShortDescription();

+

+                        // TODO: we should not see this test fail if we had the filter UI above.

+                        if (!archive.isCompatible()) {

+                            monitor.setResult("Skipping incompatible archive: %1$s", name);

+                            continue;

+                        }

+

                         archiveFile = downloadArchive(archive, monitor);

                         if (archiveFile != null) {

                             if (installArchive(archive, archiveFile, monitor)) {

-                                monitor.setResult("Installed: %1$s",

-                                        archive.getParentPackage().getShortDescription());

-                                num_installed++;

+                                monitor.setResult("Installed: %1$s", name);

+                                numInstalled++;

                             }

                         }

-                        monitor.incProgress(10);

                     } catch (Throwable t) {

                         // Display anything unexpected in the monitor.

                         monitor.setResult("Unexpected Error: %1$s", t.getMessage());

 

                     } finally {

-                        if (archiveFile != null) {

-                            if (!archiveFile.delete()) {

-                                archiveFile.deleteOnExit();

-                            }

-                        }

+                        // Delete the temp archive if it exists

+                        deleteFileOrFolder(archiveFile);

+

+                        // Always move the progress bar to the desired position.

+                        // This allows internal methods to not have to care in case

+                        // they abort early

+                        monitor.incProgress(nextProgress - monitor.getProgress());

                     }

                 }

 

-                if (num_installed == 0) {

-                    monitor.setResult("Nothing was installed.");

+                if (numInstalled == 0) {

+                    monitor.setDescription("Done. Nothing was installed.");

+                } else {

+                    monitor.setDescription("Done. %1$d %2$s installed.",

+                            numInstalled,

+                            numInstalled == 1 ? "package" : "packages");

                 }

             }

         });

@@ -397,8 +417,9 @@
             File tmpFile = File.createTempFile("sdkupload", ".bin"); //$NON-NLS-1$ //$NON-NLS-2$

             tmpFileToDelete = tmpFile;

 

-            monitor.setDescription("Downloading %1$s",

-                    archive.getParentPackage().getShortDescription());

+            String name = archive.getParentPackage().getShortDescription();

+            String desc = String.format("Downloading %1$s", name);

+            monitor.setDescription(desc);

 

             String link = archive.getUrl();

             if (!link.startsWith("http://")                          //$NON-NLS-1$

@@ -408,8 +429,7 @@
                 Package pkg = archive.getParentPackage();

                 RepoSource src = pkg.getParentSource();

                 if (src == null) {

-                    monitor.setResult("Internal error: no source for archive %1$s",

-                            archive.getShortDescription());

+                    monitor.setResult("Internal error: no source for archive %1$s", name);

                     return null;

                 }

 

@@ -422,7 +442,7 @@
                 link = base + link;

             }

 

-            if (fetchUrl(tmpFile, archive, link, monitor)) {

+            if (fetchUrl(tmpFile, archive, link, desc, monitor)) {

                 // Fetching was successful, don't delete the temp file here!

                 tmpFileToDelete = null;

                 return tmpFile;

@@ -432,11 +452,7 @@
             monitor.setResult(e.getMessage());

 

         } finally {

-            if (tmpFileToDelete != null) {

-                if (!tmpFileToDelete.delete()) {

-                    tmpFileToDelete.deleteOnExit();

-                }

-            }

+            deleteFileOrFolder(tmpFileToDelete);

         }

         return null;

     }

@@ -448,11 +464,17 @@
      * Success is defined as downloading as many bytes as was expected and having the same

      * SHA1 as expected. Returns true on success or false if any of those checks fail.

      * <p/>

-     * Increments the monitor by {@link #NUM_FETCH_URL_MONITOR_INC} (which is 10).

+     * Increments the monitor by {@link #NUM_MONITOR_INC}.

      */

-    private boolean fetchUrl(File tmpFile, Archive archive, String urlString, ITaskMonitor monitor) {

+    private boolean fetchUrl(File tmpFile,

+            Archive archive,

+            String urlString,

+            String description,

+            ITaskMonitor monitor) {

         URL url;

 

+        description += " (%1$d%%, %2$.0f KiB/s, %3$d %4$s left)";

+

         FileOutputStream os = null;

         InputStream is = null;

         try {

@@ -467,22 +489,49 @@
 

             long total = 0;

             long size = archive.getSize();

-            long inc = size / NUM_FETCH_URL_MONITOR_INC;

+            long inc = size / NUM_MONITOR_INC;

             long next_inc = inc;

 

+            long startMs = System.currentTimeMillis();

+            long nextMs = startMs + 2000;  // start update after 2 seconds

+

             while ((n = is.read(buf)) >= 0) {

                 if (n > 0) {

                     os.write(buf, 0, n);

                     digester.update(buf, 0, n);

                 }

 

+                long timeMs = System.currentTimeMillis();

+

                 total += n;

                 if (total >= next_inc) {

                     monitor.incProgress(1);

                     next_inc += inc;

                 }

 

-                if (monitor.cancelRequested()) {

+                if (timeMs > nextMs) {

+                    long delta = timeMs - startMs;

+                    if (total > 0 && delta > 0) {

+                        // percent left to download

+                        int percent = (int) (100 * total / size);

+                        // speed in KiB/s

+                        float speed = (float)total / (float)delta * (1000.f / 1024.f);

+                        // time left to download the rest at the current KiB/s rate

+                        int timeLeft = (speed > 1e-3) ?

+                                               (int)(((size - total) / 1024.0f) / speed) :

+                                               0;

+                        String timeUnit = "seconds";

+                        if (timeLeft > 120) {

+                            timeUnit = "minutes";

+                            timeLeft /= 60;

+                        }

+

+                        monitor.setDescription(description, percent, speed, timeLeft, timeUnit);

+                    }

+                    nextMs = timeMs + 1000;  // update every second

+                }

+

+                if (monitor.isCancelRequested()) {

                     monitor.setResult("Download aborted by user at %1$d bytes.", total);

                     return false;

                 }

@@ -540,14 +589,234 @@
         return false;

     }

 

+    /**

+     * Install the given archive in the given folder.

+     */

     private boolean installArchive(Archive archive, File archiveFile, ITaskMonitor monitor) {

-        monitor.setDescription("Installing %1$s", archive.getShortDescription());

+        String name = archive.getParentPackage().getShortDescription();

+        String desc = String.format("Installing %1$s", name);

+        monitor.setDescription(desc);

 

         File destFolder = archive.getParentPackage().getInstallFolder(mUpdaterData.getOsSdkRoot());

 

+        File unzipDestFolder = destFolder;

+        File renamedDestFolder = null;

+

+        try {

+            // If this folder already exists, unzip in a temporary folder and then move/unlink.

+            if (destFolder.exists()) {

+                // Find a new temp folder that doesn't exist yet

+                unzipDestFolder = findTempFolder(destFolder, "new");  //$NON-NLS-1$

+

+                if (unzipDestFolder == null) {

+                    // this should not seriously happen.

+                    monitor.setResult("Failed to find a suitable temp directory similar to %1$s.",

+                            destFolder.getPath());

+                    return false;

+                }

+

+                if (!unzipDestFolder.mkdirs()) {

+                    monitor.setResult("Failed to create temp directory %1$s",

+                            unzipDestFolder.getPath());

+                    return false;

+                }

+            }

+

+            if (!unzipFolder(archiveFile, archive.getSize(), unzipDestFolder, desc, monitor)) {

+                return false;

+            }

+

+            if (unzipDestFolder != destFolder) {

+                // Swap the old folder by the new one.

+                // Both original folders will be deleted in the finally clause below.

+                renamedDestFolder = findTempFolder(destFolder, "old");  //$NON-NLS-1$

+                if (renamedDestFolder == null) {

+                    // this should not seriously happen.

+                    monitor.setResult("Failed to find a suitable temp directory similar to %1$s.",

+                            destFolder.getPath());

+                    return false;

+                }

+

+                if (!destFolder.renameTo(renamedDestFolder)) {

+                    monitor.setResult("Failed to rename directory %1$s to %2$s",

+                            destFolder.getPath(), renamedDestFolder.getPath());

+                    return false;

+

+                }

+                if (!unzipDestFolder.renameTo(destFolder)) {

+                    monitor.setResult("Failed to rename directory %1$s to %2$s",

+                            unzipDestFolder.getPath(), destFolder.getPath());

+                    return false;

+                }

+            }

+

+            return true;

+

+        } finally {

+            // Cleanup if the unzip folder is still set.

+            deleteFileOrFolder(renamedDestFolder);

+            if (unzipDestFolder != destFolder) {

+                deleteFileOrFolder(unzipDestFolder);

+            }

+        }

+    }

+

+    private boolean unzipFolder(File archiveFile,

+            long compressedSize,

+            File unzipDestFolder,

+            String description,

+            ITaskMonitor monitor) {

+

+        description += " (%1$d%%)";

+

+        FileInputStream fis = null;

+        ZipInputStream  zis = null;

+        try {

+            fis = new FileInputStream(archiveFile);

+            zis = new ZipInputStream(fis);

+

+            // To advance the percent and the progress bar, we don't know the number of

+            // items left to unzip. However we know the size of the archive and the size of

+            // each uncompressed item. The zip file format overhead is negligible so that's

+            // a good approximation.

+            long incStep = compressedSize / NUM_MONITOR_INC;

+            long incTotal = 0;

+            long incCurr = 0;

+            int lastPercent = 0;

+

+            byte[] buf = new byte[65536];

+

+            ZipEntry entry;

+            while ((entry = zis.getNextEntry()) != null) {

+

+                String name = entry.getName();

+

+                // ZipFile entries should have forward slashes, but not all Zip

+                // implementations can be expected to do that.

+                name = name.replace('\\', '/');

+

+                File destFile = new File(unzipDestFolder, name);

+

+                if (name.endsWith("/")) {  //$NON-NLS-1$

+                    // Create directory if it doesn't exist yet. This allows us to create

+                    // empty directories.

+                    if (!destFile.isDirectory() && !destFile.mkdirs()) {

+                        monitor.setResult("Failed to create temp directory %1$s",

+                                destFile.getPath());

+                        return false;

+                    }

+                    continue;

+                } else if (name.indexOf('/') != -1) {

+                    // Otherwise it's a file in a sub-directory.

+                    // Make sure the parent directory has been created.

+                    File parentDir = destFile.getParentFile();

+                    if (!parentDir.isDirectory()) {

+                        if (!parentDir.mkdirs()) {

+                            monitor.setResult("Failed to create temp directory %1$s",

+                                    parentDir.getPath());

+                            return false;

+                        }

+                    }

+                }

+

+                FileOutputStream fos = null;

+                try {

+                    fos = new FileOutputStream(destFile);

+                    int n;

+                    while ((n = zis.read(buf)) != -1) {

+                        if (n > 0) {

+                            fos.write(buf, 0, n);

+                        }

+                    }

+                } finally {

+                    if (fos != null) {

+                        fos.close();

+                    }

+                }

+

+                // Increment progress bar to match. We update only between files.

+                for(incTotal += entry.getCompressedSize(); incCurr < incTotal; incCurr += incStep) {

+                    monitor.incProgress(1);

+                }

+

+                int percent = (int) (100 * incTotal / compressedSize);

+                if (percent != lastPercent) {

+                    monitor.setDescription(description, percent);

+                    lastPercent = percent;

+                }

+

+                if (monitor.isCancelRequested()) {

+                    return false;

+                }

+            }

+

+            return true;

+

+        } catch (IOException e) {

+            monitor.setResult("Unzip failed: %1$s", e.getMessage());

+

+        } finally {

+            if (zis != null) {

+                try {

+                    zis.close();

+                } catch (IOException e) {

+                    // pass

+                }

+            }

+            if (fis != null) {

+                try {

+                    fis.close();

+                } catch (IOException e) {

+                    // pass

+                }

+            }

+        }

+

         return false;

     }

 

+    /**

+     * Finds a temp folder which name is similar to the one of the ideal folder

+     * and with a ".tmpN" appended.

+     * <p/>

+     * This operation is not atomic so there's no guarantee the folder can't get

+     * created in between. This is however unlikely and the caller can assume the

+     * returned folder does not exist yet.

+     * <p/>

+     * Returns null if no such folder can be found (e.g. if all candidates exist),

+     * which is rather unlikely.

+     */

+    private File findTempFolder(File idealFolder, String suffix) {

+        String basePath = idealFolder.getPath();

+

+        for (int i = 1; i < 100; i++) {

+            File folder = new File(String.format("%1$s.%2$s%3$02d", basePath, suffix, i));  //$NON-NLS-1$

+            if (!folder.exists()) {

+                return folder;

+            }

+        }

+        return null;

+    }

+

+    /**

+     * Deletes a file or a directory.

+     * Directories are deleted recursively.

+     * The argument can be null.

+     */

+    private void deleteFileOrFolder(File fileOrFolder) {

+        if (fileOrFolder != null) {

+            if (fileOrFolder.isDirectory()) {

+                // Must delete content recursively first

+                for (File item : fileOrFolder.listFiles()) {

+                    deleteFileOrFolder(item);

+                }

+            }

+            if (!fileOrFolder.delete()) {

+                fileOrFolder.deleteOnExit();

+            }

+        }

+    }

+

     // End of hiding from SWT Designer

     //$hide<<$

 }

diff --git a/tools/sdkstats/src/Android.mk b/tools/sdkstats/src/Android.mk
index bff43f3..e95e67a 100644
--- a/tools/sdkstats/src/Android.mk
+++ b/tools/sdkstats/src/Android.mk
@@ -7,9 +7,9 @@
 LOCAL_JAVA_LIBRARIES := \
 	androidprefs \
 	swt \
-	org.eclipse.jface_3.2.0.I20060605-1400 \
-	org.eclipse.equinox.common_3.2.0.v20060603 \
-	org.eclipse.core.commands_3.2.0.I20060605-1400
+	org.eclipse.jface_3.4.2.M20090107-0800 \
+	org.eclipse.equinox.common_3.4.0.v20080421-2006 \
+	org.eclipse.core.commands_3.4.0.I20080509-2000
 LOCAL_MODULE := sdkstats
 
 include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/traceview/etc/traceview b/tools/traceview/etc/traceview
index 1cc913d..fc7d8c0 100755
--- a/tools/traceview/etc/traceview
+++ b/tools/traceview/etc/traceview
@@ -97,5 +97,30 @@
     jarpath="$frameworkdir/$jarfile"
 fi
 
+# Figure out the path to the swt.jar for the current architecture.
+# if ANDROID_SWT is defined, then just use this.
+# else, if running in the Android source tree, then look for the correct swt folder in prebuilt
+# else, look for the correct swt folder in the SDK under tools/lib/
+swtpath=""
+if [ -n "$ANDROID_SWT" ]; then
+    swtpath="$ANDROID_SWT"
+else
+    vmarch=`java -jar "${frameworkdir}"/archquery.jar`
+    if [ -n "$ANDROID_BUILD_TOP" ]; then
+        osname=`uname -s | tr A-Z a-z`
+        swtpath="${ANDROID_BUILD_TOP}/prebuilt/${osname}-${vmarch}/swt"
+    else
+        swtpath="${frameworkdir}/${vmarch}"
+    fi
+fi
 
-exec "$javaCmd" $javaOpts -Djava.ext.dirs="$frameworkdir" -Djava.library.path="$libdir" -jar "$jarpath" "$@"
+# Combine the swtpath and the framework dir path.
+if [ -d "$swtpath" ]; then
+    frameworkdir="${swtpath}:${frameworkdir}"
+else
+    echo "SWT folder '${swtpath}' does not exist."
+    echo "Please export ANDROID_SWT to point to the folder containing swt.jar for your platform."
+    exit 1
+fi
+
+exec "$javaCmd" $javaOpts -Djava.ext.dirs="$frameworkdir" -jar "$jarpath" "$@"
diff --git a/tools/traceview/etc/traceview.bat b/tools/traceview/etc/traceview.bat
index a9b573d..2da8a3b 100755
--- a/tools/traceview/etc/traceview.bat
+++ b/tools/traceview/etc/traceview.bat
@@ -20,24 +20,39 @@
 rem and set up progdir to be the fully-qualified pathname of its directory.
 set prog=%~f0
 
-rem Change current directory and drive to where traceview.bat is, to avoid
+rem Change current directory and drive to where the script is, to avoid
 rem issues with directories containing whitespaces.
 cd /d %~dp0
 
 set jarfile=traceview.jar
 set frameworkdir=
-set libdir=
 
 if exist %frameworkdir%%jarfile% goto JarFileOk
     set frameworkdir=lib\
-    set libdir=lib\
 
 if exist %frameworkdir%%jarfile% goto JarFileOk
     set frameworkdir=..\framework\
-    set libdir=..\lib\
 
 :JarFileOk
 
 set jarpath=%frameworkdir%%jarfile%
 
-java -Djava.ext.dirs=%frameworkdir% -Djava.library.path=%libdir% -jar %jarpath% %*
+if not defined ANDROID_SWT goto QueryArch
+    set swt_path=%ANDROID_SWT%
+    goto SwtDone
+
+:QueryArch
+
+    for /f %%a in ('java -jar %frameworkdir%archquery.jar') do set swt_path=%frameworkdir%%%a
+
+:SwtDone
+
+if exist %swt_path% goto SetPath
+    echo SWT folder '%swt_path%' does not exist.
+    echo Please set ANDROID_SWT to point to the folder containing swt.jar for your platform.
+    exit /B
+
+:SetPath
+set javaextdirs=%swt_path%;%frameworkdir%
+
+call java -Djava.ext.dirs=%javaextdirs% -jar %jarpath% %*
diff --git a/tools/traceview/src/Android.mk b/tools/traceview/src/Android.mk
index 7a006de..fd901f1 100644
--- a/tools/traceview/src/Android.mk
+++ b/tools/traceview/src/Android.mk
@@ -11,9 +11,9 @@
 	androidprefs \
 	sdkstats \
 	swt \
-	org.eclipse.jface_3.2.0.I20060605-1400 \
-	org.eclipse.equinox.common_3.2.0.v20060603 \
-	org.eclipse.core.commands_3.2.0.I20060605-1400
+	org.eclipse.jface_3.4.2.M20090107-0800 \
+	org.eclipse.equinox.common_3.4.0.v20080421-2006 \
+	org.eclipse.core.commands_3.4.0.I20080509-2000
 LOCAL_MODULE := traceview
 
 include $(BUILD_HOST_JAVA_LIBRARY)