Merge "SDK: change proguard.config for Windows."
diff --git a/anttasks/src/com/android/ant/AaptExecTask.java b/anttasks/src/com/android/ant/AaptExecTask.java
index eabbbd2..d0fba5f 100644
--- a/anttasks/src/com/android/ant/AaptExecTask.java
+++ b/anttasks/src/com/android/ant/AaptExecTask.java
@@ -93,8 +93,8 @@
     private String mResourceFilter;
     private String mRFolder;
     private final ArrayList<NoCompress> mNoCompressList = new ArrayList<NoCompress>();
-    private String mProjectLibrariesResName;
-    private String mProjectLibrariesPackageName;
+    private String mLibraryResFolderPathRefid;
+    private String mLibraryPackagesRefid;
     private boolean mNonConstantId;
 
     /**
@@ -302,15 +302,20 @@
         }
     }
 
-    public void setProjectLibrariesResName(String projectLibrariesResName) {
-        mProjectLibrariesResName = projectLibrariesResName;
+    /**
+     * Set the property name of the property that contains the list of res folder for
+     * Library Projects. This sets the name and not the value itself to handle the case where
+     * it doesn't exist.
+     * @param projectLibrariesResName
+     */
+    public void setLibraryResFolderPathRefid(String libraryResFolderPathRefid) {
+        mLibraryResFolderPathRefid = libraryResFolderPathRefid;
     }
 
-    public void setProjectLibrariesPackageName(String projectLibrariesPackageName) {
-        mProjectLibrariesPackageName = projectLibrariesPackageName;
+    public void setLibraryPackagesRefid(String libraryPackagesRefid) {
+        mLibraryPackagesRefid = libraryPackagesRefid;
     }
 
-
     /**
      * Returns an object representing a nested <var>nocompress</var> element.
      */
@@ -344,11 +349,11 @@
      */
     @Override
     public void execute() throws BuildException {
-        if (mProjectLibrariesResName == null) {
-            throw new BuildException("Missing attribute projectLibrariesResName");
+        if (mLibraryResFolderPathRefid == null) {
+            throw new BuildException("Missing attribute libraryResFolderPathRefid");
         }
-        if (mProjectLibrariesPackageName == null) {
-            throw new BuildException("Missing attribute projectLibrariesPackageName");
+        if (mLibraryPackagesRefid == null) {
+            throw new BuildException("Missing attribute libraryPackagesRefid");
         }
 
         Project taskProject = getProject();
@@ -359,7 +364,7 @@
         // more R classes need to be created for libraries, only if this project itself
         // is not a library
         if (mNonConstantId == false && mRFolder != null && new File(mRFolder).isDirectory()) {
-            libPkgProp = taskProject.getProperty(mProjectLibrariesPackageName);
+            libPkgProp = taskProject.getProperty(mLibraryPackagesRefid);
             if (libPkgProp != null) {
                 // Replace ";" with ":" since that's what aapt expects
                 libPkgProp = libPkgProp.replace(';', ':');
@@ -387,7 +392,7 @@
         final boolean generateRClass = mRFolder != null && new File(mRFolder).isDirectory();
 
         // Get whether we have libraries
-        Object libResRef = taskProject.getReference(mProjectLibrariesResName);
+        Object libResRef = taskProject.getReference(mLibraryResFolderPathRefid);
 
         // Set up our input paths that matter for dependency checks
         ArrayList<File> paths = new ArrayList<File>();
diff --git a/anttasks/src/com/android/ant/CheckEnvTask.java b/anttasks/src/com/android/ant/CheckEnvTask.java
new file mode 100644
index 0000000..d6b6cc4
--- /dev/null
+++ b/anttasks/src/com/android/ant/CheckEnvTask.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import com.android.sdklib.SdkConstants;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.util.DeweyDecimal;
+
+import java.io.File;
+
+/**
+ * Checks the Ant environment to make sure Android builds
+ * can run.
+ *
+ * No parameters are neeed.
+ *
+ */
+public class CheckEnvTask extends Task {
+
+    private final static String ANT_MIN_VERSION = "1.8.0";
+
+    @Override
+    public void execute() {
+
+        Project antProject = getProject();
+
+        // check the Ant version
+        DeweyDecimal version = getVersion(antProject);
+        DeweyDecimal atLeast = new DeweyDecimal(ANT_MIN_VERSION);
+        if (atLeast.isGreaterThan(version)) {
+            throw new BuildException(
+                    "The Android Ant-based build system requires Ant " +
+                    ANT_MIN_VERSION +
+                    " or later. Current version is " +
+                    version);
+        }
+
+        // get the SDK location
+        File sdkDir = TaskHelper.getSdkLocation(antProject);
+
+        // detect that the platform tools is there.
+        File platformTools = new File(sdkDir, SdkConstants.FD_PLATFORM_TOOLS);
+        if (platformTools.isDirectory() == false) {
+            throw new BuildException(String.format(
+                    "SDK Platform Tools component is missing. " +
+                    "Please install it with the SDK Manager (%1$s%2$c%3$s)",
+                    SdkConstants.FD_TOOLS,
+                    File.separatorChar,
+                    SdkConstants.androidCmdName()));
+        }
+
+        // display SDK Tools revision
+        int toolsRevison = TaskHelper.getToolsRevision(sdkDir);
+        if (toolsRevison != -1) {
+            System.out.println("Android SDK Tools Revision " + toolsRevison);
+            System.out.println("Installed at " + sdkDir.getAbsolutePath());
+        }
+    }
+
+    /**
+     * Returns the Ant version as a {@link DeweyDecimal} object.
+     *
+     * This is based on the implementation of
+     * org.apache.tools.ant.taskdefs.condition.AntVersion.getVersion()
+     *
+     * @param antProject the current ant project.
+     * @return the ant version.
+     */
+    private DeweyDecimal getVersion(Project antProject) {
+        char[] versionString = antProject.getProperty("ant.version").toCharArray();
+        StringBuilder sb = new StringBuilder();
+        boolean foundFirstDigit = false;
+        for (int i = 0; i < versionString.length; i++) {
+            if (Character.isDigit(versionString[i])) {
+                sb.append(versionString[i]);
+                foundFirstDigit = true;
+            }
+            if (versionString[i] == '.' && foundFirstDigit) {
+                sb.append(versionString[i]);
+            }
+            if (Character.isLetter(versionString[i]) && foundFirstDigit) {
+                break;
+            }
+        }
+        return new DeweyDecimal(sb.toString());
+    }
+
+}
diff --git a/anttasks/src/com/android/ant/ComputeDependencyTask.java b/anttasks/src/com/android/ant/ComputeDependencyTask.java
new file mode 100644
index 0000000..17b68d6
--- /dev/null
+++ b/anttasks/src/com/android/ant/ComputeDependencyTask.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import com.android.ant.DependencyHelper.LibraryProcessorFor3rdPartyJars;
+import com.android.io.FileWrapper;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.internal.project.IPropertySource;
+import com.android.sdklib.xml.AndroidManifest;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Path.PathElement;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Computes the dependency of the current project.
+ *
+ * Out params:
+ * <code>libraryResFolderPathOut</code>: the Path object containing the res folder for all the
+ * library projects in the order needed by aapt.
+ *
+ * <code>libraryPackagesOut</code>: a simple property containing ;-separated package name from
+ * the library projects.
+ *
+ * <code>jarLibraryPathOut</code>: the Path object containing all the 3rd party jar files.
+ *
+ * <code>libraryNativeFolderPathOut</code>: the Path with all the native folder for the library
+ * projects.
+ *
+ *
+ * In params:
+ * <code>targetApi</code>: the compilation target api.
+ * <code>verbose</code>: whether the build is verbose.
+ *
+ */
+public class ComputeDependencyTask extends GetLibraryListTask {
+
+    private String mLibraryResFolderPathOut;
+    private String mLibraryPackagesOut;
+    private String mJarLibraryPathOut;
+    private String mLibraryNativeFolderPathOut;
+    private int mTargetApi = -1;
+    private boolean mVerbose = false;
+
+    public void setLibraryResFolderPathOut(String libraryResFolderPathOut) {
+        mLibraryResFolderPathOut = libraryResFolderPathOut;
+    }
+
+    public void setLibraryPackagesOut(String libraryPackagesOut) {
+        mLibraryPackagesOut = libraryPackagesOut;
+    }
+
+    public void setJarLibraryPathOut(String jarLibraryPathOut) {
+        mJarLibraryPathOut = jarLibraryPathOut;
+    }
+
+    public void setLibraryNativeFolderPathOut(String libraryNativeFolderPathOut) {
+        mLibraryNativeFolderPathOut = libraryNativeFolderPathOut;
+    }
+
+    public void setTargetApi(int targetApi) {
+        mTargetApi = targetApi;
+    }
+
+    /**
+     * Sets the value of the "verbose" attribute.
+     * @param verbose the value.
+     */
+    public void setVerbose(boolean verbose) {
+        mVerbose = verbose;
+    }
+
+    @Override
+    public void execute() throws BuildException {
+        if (mLibraryResFolderPathOut == null) {
+            throw new BuildException("Missing attribute libraryResFolderPathOut");
+        }
+        if (mLibraryPackagesOut == null) {
+            throw new BuildException("Missing attribute libraryPackagesOut");
+        }
+        if (mJarLibraryPathOut == null) {
+            throw new BuildException("Missing attribute jarLibraryPathOut");
+        }
+        if (mLibraryNativeFolderPathOut == null) {
+            throw new BuildException("Missing attribute libraryNativeFolderPathOut");
+        }
+        if (mTargetApi == -1) {
+            throw new BuildException("Missing attribute targetApi");
+        }
+
+        final Project antProject = getProject();
+
+        // get the SDK location
+        File sdkDir = TaskHelper.getSdkLocation(antProject);
+
+        // prepare several paths for future tasks
+        final Path resFolderPath = new Path(antProject);
+        final Path nativeFolderPath = new Path(antProject);
+        final StringBuilder packageStrBuilder = new StringBuilder();
+
+        LibraryProcessorFor3rdPartyJars processor = new LibraryProcessorFor3rdPartyJars() {
+            @Override
+            public void processLibrary(String libRootPath) {
+                // let the super class handle the jar files
+                super.processLibrary(libRootPath);
+
+                // get the res path. Always $PROJECT/res as well as the crunch cache.
+                // FIXME: support renamed folder.
+                PathElement element = resFolderPath.createPathElement();
+                element.setPath(libRootPath + "/" + SdkConstants.FD_OUTPUT +
+                        "/" + SdkConstants.FD_RES);
+                element = resFolderPath.createPathElement();
+                element.setPath(libRootPath + "/" + SdkConstants.FD_RESOURCES);
+
+
+                // get the folder for the native libraries. Always $PROJECT/libs
+                // FIXME: support renamed folder.
+                element = nativeFolderPath.createPathElement();
+                element.setPath(libRootPath + "/" + SdkConstants.FD_NATIVE_LIBS);
+
+                // get the package from the manifest.
+                FileWrapper manifest = new FileWrapper(libRootPath,
+                        SdkConstants.FN_ANDROID_MANIFEST_XML);
+
+                try {
+                    String value = AndroidManifest.getPackage(manifest);
+                    if (value != null) { // aapt will complain if it's missing.
+                        packageStrBuilder.append(';');
+                        packageStrBuilder.append(value);
+                    }
+                } catch (Exception e) {
+                    throw new BuildException(e);
+                }
+            }
+        };
+
+        // list of all the jars that are on the classpath. This will receive the
+        // project's libs/*.jar files, the Library Projects output and their own libs/*.jar
+        List<File> jars = processor.getJars();
+
+
+        // in case clean has been called before a build type target, the list of
+        // libraries has already been computed so we don't need to compute it again.
+        Path libraryFolderPath = (Path) antProject.getReference(getLibraryFolderPathOut());
+        if (libraryFolderPath == null) {
+            execute(processor);
+        } else {
+            // this contains the list of library folder in reverse order (compilation order).
+            // We need to process it in the normal order (res order).
+            System.out.println("Ordered libraries:");
+
+            String[] libraries = libraryFolderPath.list();
+            for (int i = libraries.length - 1 ; i >= 0 ; i--) {
+                String libRootPath = libraries[i];
+                System.out.println(libRootPath);
+
+                processor.processLibrary(libRootPath);
+            }
+        }
+
+        boolean hasLibraries = jars.size() > 0;
+
+        if (mTargetApi <= 15) {
+            System.out.println("\n------------------");
+            System.out.println("API<=15: Adding annotations.jar to the classpath.");
+
+            jars.add(new File(sdkDir, SdkConstants.FD_TOOLS +
+                    "/" + SdkConstants.FD_SUPPORT +
+                    "/" + SdkConstants.FN_ANNOTATIONS_JAR));
+
+        }
+
+        // even with no libraries, always setup these so that various tasks in Ant don't complain
+        // (the task themselves can handle a ref to an empty Path)
+        antProject.addReference(mLibraryNativeFolderPathOut, nativeFolderPath);
+
+        // the rest is done only if there's a library.
+        if (hasLibraries) {
+            antProject.addReference(mLibraryResFolderPathOut, resFolderPath);
+            antProject.setProperty(mLibraryPackagesOut, packageStrBuilder.toString());
+        }
+
+        File projectFolder = antProject.getBaseDir();
+
+        // add the project's own content of libs/*.jar
+        File libsFolder = new File(projectFolder, SdkConstants.FD_NATIVE_LIBS);
+        File[] jarFiles = libsFolder.listFiles(processor.getFilter());
+        if (jarFiles != null) {
+            for (File jarFile : jarFiles) {
+                jars.add(jarFile);
+            }
+        }
+
+        // now sanitize the path to remove dups
+        jars = DependencyHelper.sanitizePaths(projectFolder, new IPropertySource() {
+            @Override
+            public String getProperty(String name) {
+                return antProject.getProperty(name);
+            }
+        }, jars);
+
+        // and create a Path object for them
+        Path jarsPath = new Path(antProject);
+        if (mVerbose) {
+            System.out.println("\n------------------\nSanitized jar list:");
+        }
+        for (File f : jars) {
+            if (mVerbose) {
+                System.out.println("- " + f.getAbsolutePath());
+            }
+            PathElement element = jarsPath.createPathElement();
+            element.setPath(f.getAbsolutePath());
+        }
+        antProject.addReference(mJarLibraryPathOut, jarsPath);
+
+        if (mVerbose) {
+            System.out.println();
+        }
+
+    }
+}
diff --git a/anttasks/src/com/android/ant/ComputeProjectClasspathTask.java b/anttasks/src/com/android/ant/ComputeProjectClasspathTask.java
new file mode 100644
index 0000000..4a89ec2
--- /dev/null
+++ b/anttasks/src/com/android/ant/ComputeProjectClasspathTask.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import com.android.ant.DependencyHelper.LibraryProcessorFor3rdPartyJars;
+import com.android.sdklib.SdkConstants;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Path.PathElement;
+
+import java.io.File;
+import java.util.List;
+
+public class ComputeProjectClasspathTask extends Task {
+
+    private String mProjectLocation;
+    private String mProjectClassPathOut;
+
+    public void setProjectLocation(String projectLocation) {
+        mProjectLocation = projectLocation;
+    }
+
+    public void setProjectClassPathOut(String projectClassPathOut) {
+        mProjectClassPathOut = projectClassPathOut;
+    }
+
+    @Override
+    public void execute() throws BuildException {
+        if (mProjectLocation == null) {
+            throw new BuildException("Missing attribute projectLocation");
+        }
+        if (mProjectClassPathOut == null) {
+            throw new BuildException("Missing attribute projectClassPathOut");
+        }
+
+        DependencyHelper helper = new DependencyHelper(new File(mProjectLocation),
+                false /*verbose*/);
+
+        LibraryProcessorFor3rdPartyJars processor = new LibraryProcessorFor3rdPartyJars();
+
+        helper.processLibraries(processor);
+        List<File> jars = processor.getJars();
+
+        // add the project's own content of libs/*.jar
+        File libsFolder = new File(mProjectLocation, SdkConstants.FD_NATIVE_LIBS);
+        File[] jarFiles = libsFolder.listFiles(processor.getFilter());
+        if (jarFiles != null) {
+            for (File jarFile : jarFiles) {
+                jars.add(jarFile);
+            }
+        }
+
+        jars = helper.sanitizePaths(jars);
+
+        Project antProject = getProject();
+
+        System.out.println("Resolved classpath:");
+
+        // create a path with all the jars and the project's output as well.
+        Path path = new Path(antProject);
+        for (File jar : jars) {
+            PathElement element = path.createPathElement();
+            String p = jar.getAbsolutePath();
+            element.setPath(p);
+            System.out.println(p);
+        }
+
+        File bin = new File(mProjectLocation,
+                helper.getOutDir() + File.separator + "classes");
+        PathElement element = path.createPathElement();
+        String p = bin.getAbsolutePath();
+        element.setPath(p);
+        System.out.println(p);
+
+        antProject.addReference(mProjectClassPathOut, path);
+    }
+}
diff --git a/anttasks/src/com/android/ant/DependencyHelper.java b/anttasks/src/com/android/ant/DependencyHelper.java
new file mode 100644
index 0000000..c2a6694
--- /dev/null
+++ b/anttasks/src/com/android/ant/DependencyHelper.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import com.android.io.FolderWrapper;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.build.JarListSanitizer;
+import com.android.sdklib.build.JarListSanitizer.DifferentLibException;
+import com.android.sdklib.build.JarListSanitizer.Sha1Exception;
+import com.android.sdklib.internal.project.IPropertySource;
+import com.android.sdklib.internal.project.ProjectProperties;
+import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
+
+import org.apache.tools.ant.BuildException;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Helper class to manage dependency for projects.
+ *
+ */
+public class DependencyHelper {
+
+    private final boolean mVerbose;
+    private final File mProjectFolder;
+    private final IPropertySource mProperties;
+    private final List<File> mLibraries = new ArrayList<File>();
+
+    /**
+     * A Library Processor. Used in {@link DependencyHelper#processLibraries(LibraryProcessor)}
+     *
+     */
+    protected interface LibraryProcessor {
+        void processLibrary(String libRootPath);
+    }
+
+    /**
+     * Basic implementation of {@link LibraryProcessor} that builds a list of sanitized list
+     * of 3rd party jar files from all the Library Projects.
+     */
+    public static class LibraryProcessorFor3rdPartyJars implements LibraryProcessor {
+
+        private final List<File> mJars = new ArrayList<File>();
+
+        private final FilenameFilter mFilter = new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                return name.toLowerCase(Locale.US).endsWith(".jar");
+            }
+        };
+
+        public List<File> getJars() {
+            return mJars;
+        }
+
+        public FilenameFilter getFilter() {
+            return mFilter;
+        }
+
+        @Override
+        public void processLibrary(String libRootPath) {
+            // get the library output
+            // FIXME: support renamed folder.
+            mJars.add(new File(libRootPath + "/" + SdkConstants.FD_OUTPUT +
+                    "/" + SdkConstants.FN_CLASSES_JAR));
+
+            // Get the 3rd party jar files.
+            // FIXME: support renamed folder.
+            File libsFolder = new File(libRootPath, SdkConstants.FD_NATIVE_LIBS);
+            File[] jarFiles = libsFolder.listFiles(mFilter);
+            if (jarFiles != null) {
+                for (File jarFile : jarFiles) {
+                    mJars.add(jarFile);
+                }
+            }
+        }
+    }
+
+    public static List<File> sanitizePaths(File projectFolder, IPropertySource properties,
+            List<File> paths) {
+        // first get the non-files.
+        List<File> results = new ArrayList<File>();
+        for (int i = 0 ; i < paths.size() ;) {
+            File f = paths.get(i);
+            // TEMP WORKAROUND: ignore classes.jar as all the output of libraries are
+            // called the same (in Ant) but are not actually the same jar file.
+            // TODO: Be aware of library output vs. regular jar dependency.
+            if (f.isFile() && f.getName().equals(SdkConstants.FN_CLASSES_JAR) == false) {
+                i++;
+            } else {
+                results.add(f);
+                paths.remove(i);
+            }
+        }
+
+
+        File outputFile = new File(projectFolder, getOutDir(properties));
+        JarListSanitizer sanitizer = new JarListSanitizer(outputFile);
+
+        try {
+            results.addAll(sanitizer.sanitize(paths));
+        } catch (DifferentLibException e) {
+            String[] details = e.getDetails();
+            for (String s : details) {
+                System.err.println(s);
+            }
+            throw new BuildException(e.getMessage(), e);
+        } catch (Sha1Exception e) {
+            throw new BuildException(
+                    "Failed to compute sha1 for " + e.getJarFile().getAbsolutePath(), e);
+        }
+
+        return results;
+    }
+
+    /**
+     *
+     * @param projectFolder the project root folder.
+     */
+    public DependencyHelper(File projectFolder, boolean verbose) {
+        mProjectFolder = projectFolder;
+        mVerbose = verbose;
+
+        ProjectProperties properties = ProjectProperties.load(projectFolder.getAbsolutePath(),
+                PropertyType.ANT);
+
+        if (properties == null) {
+            properties = ProjectProperties.load(projectFolder.getAbsolutePath(),
+                    PropertyType.PROJECT);
+        } else {
+            properties.makeWorkingCopy().merge(PropertyType.PROJECT);
+        }
+
+        mProperties = properties;
+
+        init(projectFolder);
+    }
+
+    /**
+     *
+     * @param projectFolder the project root folder.
+     * @param source an {@link IPropertySource} that can provide the project properties values.
+     */
+    public DependencyHelper(File projectFolder, IPropertySource properties, boolean verbose) {
+        mProjectFolder = projectFolder;
+        mProperties = properties;
+        mVerbose = verbose;
+
+        init(projectFolder);
+    }
+
+    private void init(File projectFolder) {
+        // get the top level list of library dependencies.
+        List<File> topLevelLibraries = getDirectDependencies(projectFolder, mProperties);
+
+        // process the libraries in case they depend on other libraries.
+        resolveFullLibraryDependencies(topLevelLibraries, mLibraries);
+    }
+
+    public List<File> getLibraries() {
+        return mLibraries;
+    }
+
+    public int getLibraryCount() {
+        return mLibraries.size();
+    }
+
+    public String getProperty(String name) {
+        return mProperties.getProperty(name);
+    }
+
+    public void processLibraries(LibraryProcessor processor) {
+        // use that same order to process the libraries.
+        for (File library : mLibraries) {
+            // get the root path.
+            String libRootPath = library.getAbsolutePath();
+            if (mVerbose) {
+                System.out.println(libRootPath);
+            }
+
+            if (processor != null) {
+                processor.processLibrary(libRootPath);
+            }
+        }
+    }
+
+    public List<File> sanitizePaths(List<File> paths) {
+        return sanitizePaths(mProjectFolder, mProperties, paths);
+    }
+
+    public String getOutDir() {
+        return getOutDir(mProperties);
+    }
+
+
+    /**
+     * Returns the top level library dependencies of a given <var>source</var> representing a
+     * project properties.
+     * @param baseFolder the base folder of the project (to resolve relative paths)
+     * @param properties a source of project properties.
+     */
+    private List<File> getDirectDependencies(File baseFolder, IPropertySource properties) {
+        ArrayList<File> libraries = new ArrayList<File>();
+
+        // first build the list. they are ordered highest priority first.
+        int index = 1;
+        while (true) {
+            String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
+            String rootPath = properties.getProperty(propName);
+
+            if (rootPath == null) {
+                break;
+            }
+
+            try {
+                File library = new File(baseFolder, rootPath).getCanonicalFile();
+
+                // check for validity
+                File projectProp = new File(library, PropertyType.PROJECT.getFilename());
+                if (projectProp.isFile() == false) {
+                    // error!
+                    throw new BuildException(String.format(
+                            "%1$s resolve to a path with no %2$s file for project %3$s", rootPath,
+                            PropertyType.PROJECT.getFilename(), baseFolder.getAbsolutePath()));
+                }
+
+                if (libraries.contains(library) == false) {
+                    if (mVerbose) {
+                        System.out.println(String.format("%1$s: %2$s => %3$s",
+                                baseFolder.getAbsolutePath(), rootPath, library.getAbsolutePath()));
+                    }
+
+                    libraries.add(library);
+                }
+            } catch (IOException e) {
+                throw new BuildException("Failed to resolve library path: " + rootPath, e);
+            }
+        }
+
+        return libraries;
+    }
+
+    /**
+     * Resolves a given list of libraries, finds out if they depend on other libraries, and
+     * returns a full list of all the direct and indirect dependencies in the proper order (first
+     * is higher priority when calling aapt).
+     * @param inLibraries the libraries to resolve
+     * @param outLibraries where to store all the libraries.
+     */
+    private void resolveFullLibraryDependencies(List<File> inLibraries, List<File> outLibraries) {
+        // loop in the inverse order to resolve dependencies on the libraries, so that if a library
+        // is required by two higher level libraries it can be inserted in the correct place
+        for (int i = inLibraries.size() - 1  ; i >= 0 ; i--) {
+            File library = inLibraries.get(i);
+
+            // get the default.property file for it
+            final ProjectProperties projectProp = ProjectProperties.load(
+                    new FolderWrapper(library), PropertyType.PROJECT);
+
+            // get its libraries
+            List<File> dependencies = getDirectDependencies(library, projectProp);
+
+            // resolve the dependencies for those libraries
+            resolveFullLibraryDependencies(dependencies, outLibraries);
+
+            // and add the current one (if needed) in front (higher priority)
+            if (outLibraries.contains(library) == false) {
+                outLibraries.add(0, library);
+            }
+        }
+    }
+
+    private static String getOutDir(IPropertySource properties) {
+        String bin = properties.getProperty("out.dir");
+        if (bin == null) {
+            return SdkConstants.FD_OUTPUT;
+        }
+
+        return bin;
+    }
+
+}
diff --git a/anttasks/src/com/android/ant/GetEmmaFilterTask.java b/anttasks/src/com/android/ant/GetEmmaFilterTask.java
new file mode 100644
index 0000000..f449f8d
--- /dev/null
+++ b/anttasks/src/com/android/ant/GetEmmaFilterTask.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+
+/**
+ * Task building an emma filter to remove all build-only classes.
+ *
+ * Currently ignore:
+ * app.package.R
+ * app.package.R$*
+ * app.package.Manifest
+ * app.package.BuildConfig
+ *
+ */
+public class GetEmmaFilterTask extends Task {
+
+    private static final String[] FILTER_CLASSES = new String[] {
+        "R", "R$*", "Manifest", "BuildConfig"
+    };
+
+    private String mAppPackage;
+    private String mLibraryPackagesRefId;
+    private String mFilterOut;
+
+
+    public void setAppPackage(String appPackage) {
+        mAppPackage = appPackage;
+    }
+
+    public void setLibraryPackagesRefId(String libraryPackagesRefId) {
+        mLibraryPackagesRefId = libraryPackagesRefId;
+    }
+
+    public void setFilterOut(String filterOut) {
+        mFilterOut = filterOut;
+    }
+
+    @Override
+    public void execute() throws BuildException {
+        if (mAppPackage == null) {
+            throw new BuildException("Missing attribute appPackage");
+        }
+        if (mLibraryPackagesRefId == null) {
+            throw new BuildException("Missing attribute libraryPackagesRefId");
+        }
+        if (mFilterOut == null) {
+            throw new BuildException("Missing attribute filterOut");
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        String libraryPackagesValue = getProject().getProperty(mLibraryPackagesRefId);
+
+        if (libraryPackagesValue != null && libraryPackagesValue.length() > 0) {
+            // split the app packages.
+            String[] libPackages = libraryPackagesValue.split(";");
+
+            for (String libPackage : libPackages) {
+                if (libPackage.length() > 0) {
+                    for (String filterClass : FILTER_CLASSES) {
+                        sb.append(libPackage).append('.').append(filterClass).append(',');
+                    }
+                }
+            }
+        }
+
+        // add the app package:
+        final int count = FILTER_CLASSES.length;
+        for (int i = 0 ; i < count ; i++) {
+            sb.append(mAppPackage).append('.').append(FILTER_CLASSES[i]);
+            if (i < count - 1) {
+                sb.append(',');
+            }
+        }
+
+        getProject().setProperty(mFilterOut, sb.toString());
+    }
+}
diff --git a/anttasks/src/com/android/ant/GetLibraryListTask.java b/anttasks/src/com/android/ant/GetLibraryListTask.java
new file mode 100644
index 0000000..e2d5dd7
--- /dev/null
+++ b/anttasks/src/com/android/ant/GetLibraryListTask.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import com.android.ant.DependencyHelper.LibraryProcessor;
+import com.android.sdklib.internal.project.IPropertySource;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Path.PathElement;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * Task to get the list of Library Project for the current project.
+ *
+ */
+public class GetLibraryListTask extends Task {
+
+    private String mLibraryFolderPathOut;
+
+
+    public void setLibraryFolderPathOut(String libraryFolderPathOut) {
+        mLibraryFolderPathOut = libraryFolderPathOut;
+    }
+
+    @Override
+    public void execute() throws BuildException {
+        execute(null);
+    }
+
+    public void execute(LibraryProcessor processor) throws BuildException {
+
+        if (mLibraryFolderPathOut == null) {
+            throw new BuildException("Missing attribute libraryFolderPathOut");
+        }
+
+        final Project antProject = getProject();
+
+        DependencyHelper helper = new DependencyHelper(antProject.getBaseDir(),
+                new IPropertySource() {
+                    @Override
+                    public String getProperty(String name) {
+                        return antProject.getProperty(name);
+                    }
+                },
+                true /*verbose*/);
+
+        System.out.println("Library dependencies:");
+
+        if (helper.getLibraryCount() > 0) {
+            System.out.println("\n------------------\nOrdered libraries:");
+
+            helper.processLibraries(processor);
+
+            // Create a Path object of all the libraries in reverse order.
+            // This is important so that compilation of libraries happens
+            // in the reverse order.
+            Path rootPath = new Path(antProject);
+
+            List<File> libraries = helper.getLibraries();
+
+            for (int i = libraries.size() - 1 ; i >= 0; i--) {
+                File library = libraries.get(i);
+                PathElement element = rootPath.createPathElement();
+                element.setPath(library.getAbsolutePath());
+            }
+
+            antProject.addReference(mLibraryFolderPathOut, rootPath);
+        } else {
+            System.out.println("No Libraries");
+        }
+    }
+
+    protected String getLibraryFolderPathOut() {
+        return mLibraryFolderPathOut;
+    }
+}
diff --git a/anttasks/src/com/android/ant/GetTargetTask.java b/anttasks/src/com/android/ant/GetTargetTask.java
new file mode 100644
index 0000000..f4578b2
--- /dev/null
+++ b/anttasks/src/com/android/ant/GetTargetTask.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import com.android.sdklib.AndroidVersion;
+import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
+import com.android.sdklib.ISdkLog;
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.SdkManager;
+import com.android.sdklib.internal.project.ProjectProperties;
+import com.android.sdklib.xml.AndroidManifest;
+import com.android.sdklib.xml.AndroidXPathFactory;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Path.PathElement;
+import org.xml.sax.InputSource;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.HashSet;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+
+/**
+ * Task to resolve the target of the current Android project.
+ *
+ * Out params:
+ * <code>bootClassPathOut</code>: The boot class path of the project.
+ *
+ * <code>androidJarFileOut</code>: the android.jar used by the project.
+ *
+ * <code>androidAidlFileOut</code>: the framework.aidl used by the project.
+ *
+ * <code>targetApiOut</code>: the build API level.
+ *
+ * <code>minSdkVersionOut</code>: the app's minSdkVersion.
+ *
+ */
+public class GetTargetTask extends Task {
+
+    private String mBootClassPathOut;
+    private String mAndroidJarFileOut;
+    private String mAndroidAidlFileOut;
+    private String mTargetApiOut;
+    private String mMinSdkVersionOut;
+
+    public void setBootClassPathOut(String bootClassPathOut) {
+        mBootClassPathOut = bootClassPathOut;
+    }
+
+    public void setAndroidJarFileOut(String androidJarFileOut) {
+        mAndroidJarFileOut = androidJarFileOut;
+    }
+
+    public void setAndroidAidlFileOut(String androidAidlFileOut) {
+        mAndroidAidlFileOut = androidAidlFileOut;
+    }
+
+    public void setTargetApiOut(String targetApiOut) {
+        mTargetApiOut = targetApiOut;
+    }
+
+    public void setMinSdkVersionOut(String minSdkVersionOut) {
+        mMinSdkVersionOut = minSdkVersionOut;
+    }
+
+    @Override
+    public void execute() throws BuildException {
+        if (mBootClassPathOut == null) {
+            throw new BuildException("Missing attribute bootClassPathOut");
+        }
+        if (mAndroidJarFileOut == null) {
+            throw new BuildException("Missing attribute androidJarFileOut");
+        }
+        if (mAndroidAidlFileOut == null) {
+            throw new BuildException("Missing attribute androidAidlFileOut");
+        }
+        if (mTargetApiOut == null) {
+            throw new BuildException("Missing attribute targetApiOut");
+        }
+        if (mMinSdkVersionOut == null) {
+            throw new BuildException("Missing attribute mMinSdkVersionOut");
+        }
+
+        Project antProject = getProject();
+
+        // get the SDK location
+        File sdkDir = TaskHelper.getSdkLocation(antProject);
+
+        // get the target property value
+        String targetHashString = antProject.getProperty(ProjectProperties.PROPERTY_TARGET);
+
+        if (targetHashString == null) {
+            throw new BuildException("Android Target is not set.");
+        }
+
+        // load up the sdk targets.
+        final ArrayList<String> messages = new ArrayList<String>();
+        SdkManager manager = SdkManager.createManager(sdkDir.getPath(), new ISdkLog() {
+            @Override
+            public void error(Throwable t, String errorFormat, Object... args) {
+                if (errorFormat != null) {
+                    messages.add(String.format("Error: " + errorFormat, args));
+                }
+                if (t != null) {
+                    messages.add("Error: " + t.getMessage());
+                }
+            }
+
+            @Override
+            public void printf(String msgFormat, Object... args) {
+                messages.add(String.format(msgFormat, args));
+            }
+
+            @Override
+            public void warning(String warningFormat, Object... args) {
+                messages.add(String.format("Warning: " + warningFormat, args));
+            }
+        });
+
+        if (manager == null) {
+            // since we failed to parse the SDK, lets display the parsing output.
+            for (String msg : messages) {
+                System.out.println(msg);
+            }
+            throw new BuildException("Failed to parse SDK content.");
+        }
+
+        // resolve it
+        IAndroidTarget androidTarget = manager.getTargetFromHashString(targetHashString);
+
+        if (androidTarget == null) {
+            throw new BuildException(String.format(
+                    "Unable to resolve project target '%s'", targetHashString));
+        }
+
+        // display the project info
+        System.out.println(    "Project Target:   " + androidTarget.getName());
+        if (androidTarget.isPlatform() == false) {
+            System.out.println("Vendor:           " + androidTarget.getVendor());
+            System.out.println("Platform Version: " + androidTarget.getVersionName());
+        }
+        System.out.println(    "API level:        " + androidTarget.getVersion().getApiString());
+
+        antProject.setProperty(mMinSdkVersionOut,
+                Integer.toString(androidTarget.getVersion().getApiLevel()));
+
+        // always check the manifest minSdkVersion.
+        checkManifest(antProject, androidTarget.getVersion());
+
+        // sets up the properties to find android.jar/framework.aidl/target tools
+        String androidJar = androidTarget.getPath(IAndroidTarget.ANDROID_JAR);
+        antProject.setProperty(mAndroidJarFileOut, androidJar);
+
+        String androidAidl = androidTarget.getPath(IAndroidTarget.ANDROID_AIDL);
+        antProject.setProperty(mAndroidAidlFileOut, androidAidl);
+
+        // sets up the boot classpath
+
+        // create the Path object
+        Path bootclasspath = new Path(antProject);
+
+        // create a PathElement for the framework jar
+        PathElement element = bootclasspath.createPathElement();
+        element.setPath(androidJar);
+
+        // create PathElement for each optional library.
+        IOptionalLibrary[] libraries = androidTarget.getOptionalLibraries();
+        if (libraries != null) {
+            HashSet<String> visitedJars = new HashSet<String>();
+            for (IOptionalLibrary library : libraries) {
+                String jarPath = library.getJarPath();
+                if (visitedJars.contains(jarPath) == false) {
+                    visitedJars.add(jarPath);
+
+                    element = bootclasspath.createPathElement();
+                    element.setPath(library.getJarPath());
+                }
+            }
+        }
+
+        // sets the path in the project with a reference
+        antProject.addReference(mBootClassPathOut, bootclasspath);
+    }
+
+    /**
+     * Checks the manifest <code>minSdkVersion</code> attribute.
+     * @param antProject the ant project
+     * @param androidVersion the version of the platform the project is compiling against.
+     */
+    private void checkManifest(Project antProject, AndroidVersion androidVersion) {
+        try {
+            File manifest = new File(antProject.getBaseDir(), SdkConstants.FN_ANDROID_MANIFEST_XML);
+
+            XPath xPath = AndroidXPathFactory.newXPath();
+
+            // check the package name.
+            String value = xPath.evaluate(
+                    "/"  + AndroidManifest.NODE_MANIFEST +
+                    "/@" + AndroidManifest.ATTRIBUTE_PACKAGE,
+                    new InputSource(new FileInputStream(manifest)));
+            if (value != null) { // aapt will complain if it's missing.
+                // only need to check that the package has 2 segments
+                if (value.indexOf('.') == -1) {
+                    throw new BuildException(String.format(
+                            "Application package '%1$s' must have a minimum of 2 segments.",
+                            value));
+                }
+            }
+
+            // check the minSdkVersion value
+            value = xPath.evaluate(
+                    "/"  + AndroidManifest.NODE_MANIFEST +
+                    "/"  + AndroidManifest.NODE_USES_SDK +
+                    "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + ":" +
+                            AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
+                    new InputSource(new FileInputStream(manifest)));
+
+            if (androidVersion.isPreview()) {
+                // in preview mode, the content of the minSdkVersion must match exactly the
+                // platform codename.
+                String codeName = androidVersion.getCodename();
+                if (codeName.equals(value) == false) {
+                    throw new BuildException(String.format(
+                            "For '%1$s' SDK Preview, attribute minSdkVersion in AndroidManifest.xml must be '%1$s' (current: %2$s)",
+                            codeName, value));
+                }
+
+                // set the API level to the previous API level (which is actually the value in
+                // androidVersion.)
+                antProject.setProperty(mTargetApiOut,
+                        Integer.toString(androidVersion.getApiLevel()));
+
+            } else if (value.length() > 0) {
+                // for normal platform, we'll only display warnings if the value is lower or higher
+                // than the target api level.
+                // First convert to an int.
+                int minSdkValue = -1;
+                try {
+                    minSdkValue = Integer.parseInt(value);
+                } catch (NumberFormatException e) {
+                    // looks like it's not a number: error!
+                    throw new BuildException(String.format(
+                            "Attribute %1$s in AndroidManifest.xml must be an Integer!",
+                            AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION));
+                }
+
+                // set the target api to the value
+                antProject.setProperty(mTargetApiOut, value);
+
+                int projectApiLevel = androidVersion.getApiLevel();
+                if (minSdkValue > androidVersion.getApiLevel()) {
+                    System.out.println(String.format(
+                            "WARNING: Attribute %1$s in AndroidManifest.xml (%2$d) is higher than the project target API level (%3$d)",
+                            AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
+                            minSdkValue, projectApiLevel));
+                }
+            } else {
+                // no minSdkVersion? display a warning
+                System.out.println(
+                        "WARNING: No minSdkVersion value set. Application will install on all Android versions.");
+
+                // set the target api to 1
+                antProject.setProperty(mTargetApiOut, "1");
+            }
+
+        } catch (XPathExpressionException e) {
+            throw new BuildException(e);
+        } catch (FileNotFoundException e) {
+            throw new BuildException(e);
+        }
+    }
+}
diff --git a/anttasks/src/com/android/ant/GetTypeTask.java b/anttasks/src/com/android/ant/GetTypeTask.java
new file mode 100644
index 0000000..b11e9f2
--- /dev/null
+++ b/anttasks/src/com/android/ant/GetTypeTask.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ant;
+
+import com.android.sdklib.SdkConstants;
+import com.android.sdklib.internal.project.ProjectProperties;
+import com.android.sdklib.xml.AndroidManifest;
+import com.android.sdklib.xml.AndroidXPathFactory;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.xml.sax.InputSource;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathExpressionException;
+
+/**
+ * Task to query the type of the current project.
+ *
+ * Out params:
+ *
+ * <code>projectTypeOut</code>: String value containing the type of the project. Possible values
+ * are 'app', 'library', 'test', 'test-app'
+ *
+ */
+public class GetTypeTask extends Task {
+
+    private String mProjectTypeOut;
+
+    public void setProjectTypeOut(String projectTypeOut) {
+        mProjectTypeOut = projectTypeOut;
+    }
+
+    @Override
+    public void execute() throws BuildException {
+        if (mProjectTypeOut == null) {
+            throw new BuildException("Missing attribute projectTypeOut");
+        }
+
+        Project antProject = getProject();
+
+        String libraryProp = antProject.getProperty(ProjectProperties.PROPERTY_LIBRARY);
+        if (libraryProp != null) {
+            if (Boolean.valueOf(libraryProp).booleanValue()) {
+                System.out.println("Project Type: Android Library");
+
+                antProject.setProperty(mProjectTypeOut, "library");
+                return;
+            }
+        }
+
+        if (antProject.getProperty(ProjectProperties.PROPERTY_TESTED_PROJECT) != null) {
+            System.out.println("Project Type: Test Application");
+
+            antProject.setProperty(mProjectTypeOut, "test");
+            return;
+        }
+
+        // we also need to check if the Manifest doesn't have some instrumentation which
+        // means the app is a self-contained test project.
+        try {
+            File manifest = new File(antProject.getBaseDir(), SdkConstants.FN_ANDROID_MANIFEST_XML);
+            XPath xPath = AndroidXPathFactory.newXPath();
+
+            // check the present of /manifest/instrumentation/
+            String value = xPath.evaluate(
+                    "/"  + AndroidManifest.NODE_MANIFEST +
+                    "/" + AndroidManifest.NODE_INSTRUMENTATION +
+                    "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX +
+                    ":" + AndroidManifest.ATTRIBUTE_TARGET_PACKAGE,
+                    new InputSource(new FileInputStream(manifest)));
+
+            if (value != null && value.length() > 0) {
+                System.out.println("Project Type: Self-Tested Application");
+
+                antProject.setProperty(mProjectTypeOut, "test-app");
+                return;
+            }
+        } catch (XPathExpressionException e) {
+            throw new BuildException(e);
+        } catch (FileNotFoundException e) {
+            throw new BuildException(e);
+        }
+
+        // default case
+        System.out.println("Project Type: Application");
+
+        antProject.setProperty(mProjectTypeOut, "app");
+    }
+}
diff --git a/anttasks/src/com/android/ant/NewSetupTask.java b/anttasks/src/com/android/ant/NewSetupTask.java
deleted file mode 100644
index c74b946..0000000
--- a/anttasks/src/com/android/ant/NewSetupTask.java
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * 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.ant;
-
-import com.android.io.FileWrapper;
-import com.android.io.FolderWrapper;
-import com.android.sdklib.AndroidVersion;
-import com.android.sdklib.IAndroidTarget;
-import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
-import com.android.sdklib.ISdkLog;
-import com.android.sdklib.SdkConstants;
-import com.android.sdklib.SdkManager;
-import com.android.sdklib.build.JarListSanitizer;
-import com.android.sdklib.build.JarListSanitizer.DifferentLibException;
-import com.android.sdklib.build.JarListSanitizer.Sha1Exception;
-import com.android.sdklib.internal.project.ProjectProperties;
-import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
-import com.android.sdklib.xml.AndroidManifest;
-import com.android.sdklib.xml.AndroidXPathFactory;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.types.Path;
-import org.apache.tools.ant.types.Path.PathElement;
-import org.apache.tools.ant.util.DeweyDecimal;
-import org.xml.sax.InputSource;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathExpressionException;
-
-/**
- * Setup Ant task. This task accomplishes:
- * <ul>
- * <li>Gets the project target hash string from {@link ProjectProperties#PROPERTY_TARGET},
- * and resolves it to get the project's {@link IAndroidTarget}.</li>
- *
- * <li>Sets up properties so that aapt can find the android.jar and other files/folders in
- * the resolved target.</li>
- *
- * <li>Sets up the boot classpath ref so that the <code>javac</code> task knows where to find
- * the libraries. This includes the default android.jar from the resolved target but also optional
- * libraries provided by the target (if any, when the target is an add-on).</li>
- *
- * <li>Resolve library dependencies and setup various Path references for them</li>
- * </ul>
- *
- * This is used in the main rules file only.
- *
- */
-public class NewSetupTask extends Task {
-    private final static String ANT_MIN_VERSION = "1.8.0";
-
-    private String mProjectTypeOut;
-    private String mAndroidJarFileOut;
-    private String mAndroidAidlFileOut;
-    private String mRenderScriptExeOut;
-    private String mRenderScriptIncludeDirOut;
-    private String mBootclasspathrefOut;
-    private String mProjectLibrariesRootOut;
-    private String mProjectLibrariesResOut;
-    private String mProjectLibrariesPackageOut;
-    private String mProjectLibrariesJarsOut;
-    private String mProjectLibrariesLibsOut;
-    private String mTargetApiOut;
-    private boolean mVerbose = false;
-
-    public void setProjectTypeOut(String projectTypeOut) {
-        mProjectTypeOut = projectTypeOut;
-    }
-
-    public void setAndroidJarFileOut(String androidJarFileOut) {
-        mAndroidJarFileOut = androidJarFileOut;
-    }
-
-    public void setAndroidAidlFileOut(String androidAidlFileOut) {
-        mAndroidAidlFileOut = androidAidlFileOut;
-    }
-
-    public void setRenderScriptExeOut(String renderScriptExeOut) {
-        mRenderScriptExeOut = renderScriptExeOut;
-    }
-
-    public void setRenderScriptIncludeDirOut(String renderScriptIncludeDirOut) {
-        mRenderScriptIncludeDirOut = renderScriptIncludeDirOut;
-    }
-
-    public void setBootclasspathrefOut(String bootclasspathrefOut) {
-        mBootclasspathrefOut = bootclasspathrefOut;
-    }
-
-    public void setProjectLibrariesRootOut(String projectLibrariesRootOut) {
-        mProjectLibrariesRootOut = projectLibrariesRootOut;
-    }
-
-    public void setProjectLibrariesResOut(String projectLibrariesResOut) {
-        mProjectLibrariesResOut = projectLibrariesResOut;
-    }
-
-    public void setProjectLibrariesPackageOut(String projectLibrariesPackageOut) {
-        mProjectLibrariesPackageOut = projectLibrariesPackageOut;
-    }
-
-    public void setProjectLibrariesJarsOut(String projectLibrariesJarsOut) {
-        mProjectLibrariesJarsOut = projectLibrariesJarsOut;
-    }
-
-    public void setProjectLibrariesLibsOut(String projectLibrariesLibsOut) {
-        mProjectLibrariesLibsOut = projectLibrariesLibsOut;
-    }
-
-    public void setTargetApiOut(String targetApiOut) {
-        mTargetApiOut = targetApiOut;
-    }
-
-    /**
-     * Sets the value of the "verbose" attribute.
-     * @param verbose the value.
-     */
-    public void setVerbose(boolean verbose) {
-        mVerbose = verbose;
-    }
-
-    @Override
-    public void execute() throws BuildException {
-        if (mProjectTypeOut == null) {
-            throw new BuildException("Missing attribute projectTypeOut");
-        }
-        if (mAndroidJarFileOut == null) {
-            throw new BuildException("Missing attribute androidJarFileOut");
-        }
-        if (mAndroidAidlFileOut == null) {
-            throw new BuildException("Missing attribute androidAidlFileOut");
-        }
-        if (mRenderScriptExeOut == null) {
-            throw new BuildException("Missing attribute renderScriptExeOut");
-        }
-        if (mRenderScriptIncludeDirOut == null) {
-            throw new BuildException("Missing attribute renderScriptIncludeDirOut");
-        }
-        if (mBootclasspathrefOut == null) {
-            throw new BuildException("Missing attribute bootclasspathrefOut");
-        }
-        if (mProjectLibrariesRootOut == null) {
-            throw new BuildException("Missing attribute projectLibrariesRootOut");
-        }
-        if (mProjectLibrariesResOut == null) {
-            throw new BuildException("Missing attribute projectLibrariesResOut");
-        }
-        if (mProjectLibrariesPackageOut == null) {
-            throw new BuildException("Missing attribute projectLibrariesPackageOut");
-        }
-        if (mProjectLibrariesJarsOut == null) {
-            throw new BuildException("Missing attribute projectLibrariesJarsOut");
-        }
-        if (mProjectLibrariesLibsOut == null) {
-            throw new BuildException("Missing attribute projectLibrariesLibsOut");
-        }
-        if (mTargetApiOut == null) {
-            throw new BuildException("Missing attribute targetApiOut");
-        }
-
-
-        Project antProject = getProject();
-
-        // check the Ant version
-        DeweyDecimal version = getVersion(antProject);
-        DeweyDecimal atLeast = new DeweyDecimal(ANT_MIN_VERSION);
-        if (atLeast.isGreaterThan(version)) {
-            throw new BuildException(
-                    "The Android Ant-based build system requires Ant " +
-                    ANT_MIN_VERSION +
-                    " or later. Current version is " +
-                    version);
-        }
-
-        // get the SDK location
-        File sdkDir = TaskHelper.getSdkLocation(antProject);
-        String sdkOsPath = sdkDir.getPath();
-
-        // Make sure the OS sdk path ends with a directory separator
-        if (sdkOsPath.length() > 0 && !sdkOsPath.endsWith(File.separator)) {
-            sdkOsPath += File.separator;
-        }
-
-        // display SDK Tools revision
-        int toolsRevison = TaskHelper.getToolsRevision(sdkDir);
-        if (toolsRevison != -1) {
-            System.out.println("Android SDK Tools Revision " + toolsRevison);
-        }
-
-        // detect that the platform tools is there.
-        File platformTools = new File(sdkDir, SdkConstants.FD_PLATFORM_TOOLS);
-        if (platformTools.isDirectory() == false) {
-            throw new BuildException(String.format(
-                    "SDK Platform Tools component is missing. " +
-                    "Please install it with the SDK Manager (%1$s%2$c%3$s)",
-                    SdkConstants.FD_TOOLS,
-                    File.separatorChar,
-                    SdkConstants.androidCmdName()));
-        }
-
-        // get the target property value
-        String targetHashString = antProject.getProperty(ProjectProperties.PROPERTY_TARGET);
-
-        boolean isTestProject = false;
-
-        if (antProject.getProperty(ProjectProperties.PROPERTY_TESTED_PROJECT) != null) {
-            isTestProject = true;
-        }
-
-        if (targetHashString == null) {
-            throw new BuildException("Android Target is not set.");
-        }
-
-        // load up the sdk targets.
-        final ArrayList<String> messages = new ArrayList<String>();
-        SdkManager manager = SdkManager.createManager(sdkOsPath, new ISdkLog() {
-            @Override
-            public void error(Throwable t, String errorFormat, Object... args) {
-                if (errorFormat != null) {
-                    messages.add(String.format("Error: " + errorFormat, args));
-                }
-                if (t != null) {
-                    messages.add("Error: " + t.getMessage());
-                }
-            }
-
-            @Override
-            public void printf(String msgFormat, Object... args) {
-                messages.add(String.format(msgFormat, args));
-            }
-
-            @Override
-            public void warning(String warningFormat, Object... args) {
-                messages.add(String.format("Warning: " + warningFormat, args));
-            }
-        });
-
-        if (manager == null) {
-            // since we failed to parse the SDK, lets display the parsing output.
-            for (String msg : messages) {
-                System.out.println(msg);
-            }
-            throw new BuildException("Failed to parse SDK content.");
-        }
-
-        // resolve it
-        IAndroidTarget androidTarget = manager.getTargetFromHashString(targetHashString);
-
-        if (androidTarget == null) {
-            throw new BuildException(String.format(
-                    "Unable to resolve target '%s'", targetHashString));
-        }
-
-        // display the project info
-        System.out.println("Project Target: " + androidTarget.getName());
-        if (androidTarget.isPlatform() == false) {
-            System.out.println("Vendor: " + androidTarget.getVendor());
-            System.out.println("Platform Version: " + androidTarget.getVersionName());
-        }
-        System.out.println("API level: " + androidTarget.getVersion().getApiString());
-
-        // check if the project is a library
-        boolean isLibrary = false;
-
-        String libraryProp = antProject.getProperty(ProjectProperties.PROPERTY_LIBRARY);
-        if (libraryProp != null) {
-            isLibrary = Boolean.valueOf(libraryProp).booleanValue();
-        }
-
-        if (isLibrary) {
-            System.out.println("Project Type: Android Library");
-        }
-
-        // look for referenced libraries.
-        processReferencedLibraries(antProject, androidTarget, sdkOsPath);
-
-        // always check the manifest minSdkVersion.
-        checkManifest(antProject, androidTarget.getVersion());
-
-        // sets up the properties to find android.jar/framework.aidl/target tools
-        String androidJar = androidTarget.getPath(IAndroidTarget.ANDROID_JAR);
-        antProject.setProperty(mAndroidJarFileOut, androidJar);
-
-        String androidAidl = androidTarget.getPath(IAndroidTarget.ANDROID_AIDL);
-        antProject.setProperty(mAndroidAidlFileOut, androidAidl);
-
-        Path includePath = new Path(antProject);
-        PathElement element = includePath.createPathElement();
-        element.setPath(androidTarget.getPath(IAndroidTarget.ANDROID_RS));
-        element = includePath.createPathElement();
-        element.setPath(androidTarget.getPath(IAndroidTarget.ANDROID_RS_CLANG));
-        antProject.setProperty(mRenderScriptIncludeDirOut, includePath.toString());
-
-        // TODO: figure out the actual compiler to use based on the minSdkVersion
-        antProject.setProperty(mRenderScriptExeOut,
-                sdkOsPath + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER +
-                SdkConstants.FN_RENDERSCRIPT);
-
-        // sets up the boot classpath
-
-        // create the Path object
-        Path bootclasspath = new Path(antProject);
-
-        // create a PathElement for the framework jar
-        element = bootclasspath.createPathElement();
-        element.setPath(androidJar);
-
-        // create PathElement for each optional library.
-        IOptionalLibrary[] libraries = androidTarget.getOptionalLibraries();
-        if (libraries != null) {
-            HashSet<String> visitedJars = new HashSet<String>();
-            for (IOptionalLibrary library : libraries) {
-                String jarPath = library.getJarPath();
-                if (visitedJars.contains(jarPath) == false) {
-                    visitedJars.add(jarPath);
-
-                    element = bootclasspath.createPathElement();
-                    element.setPath(library.getJarPath());
-                }
-            }
-        }
-
-        // sets the path in the project with a reference
-        antProject.addReference(mBootclasspathrefOut, bootclasspath);
-
-        // finally set the project type.
-        if (isLibrary) {
-            antProject.setProperty(mProjectTypeOut, "library");
-        } else if (isTestProject) {
-            antProject.setProperty(mProjectTypeOut, "test");
-        } else {
-            antProject.setProperty(mProjectTypeOut, "project");
-        }
-    }
-
-    /**
-     * Checks the manifest <code>minSdkVersion</code> attribute.
-     * @param antProject the ant project
-     * @param androidVersion the version of the platform the project is compiling against.
-     */
-    private void checkManifest(Project antProject, AndroidVersion androidVersion) {
-        try {
-            File manifest = new File(antProject.getBaseDir(), SdkConstants.FN_ANDROID_MANIFEST_XML);
-
-            XPath xPath = AndroidXPathFactory.newXPath();
-
-            // check the package name.
-            String value = xPath.evaluate(
-                    "/"  + AndroidManifest.NODE_MANIFEST +
-                    "/@" + AndroidManifest.ATTRIBUTE_PACKAGE,
-                    new InputSource(new FileInputStream(manifest)));
-            if (value != null) { // aapt will complain if it's missing.
-                // only need to check that the package has 2 segments
-                if (value.indexOf('.') == -1) {
-                    throw new BuildException(String.format(
-                            "Application package '%1$s' must have a minimum of 2 segments.",
-                            value));
-                }
-            }
-
-            // check the minSdkVersion value
-            value = xPath.evaluate(
-                    "/"  + AndroidManifest.NODE_MANIFEST +
-                    "/"  + AndroidManifest.NODE_USES_SDK +
-                    "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + ":" +
-                            AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
-                    new InputSource(new FileInputStream(manifest)));
-
-            if (androidVersion.isPreview()) {
-                // in preview mode, the content of the minSdkVersion must match exactly the
-                // platform codename.
-                String codeName = androidVersion.getCodename();
-                if (codeName.equals(value) == false) {
-                    throw new BuildException(String.format(
-                            "For '%1$s' SDK Preview, attribute minSdkVersion in AndroidManifest.xml must be '%1$s' (current: %2$s)",
-                            codeName, value));
-                }
-
-                // set the API level to the previous API level (which is actually the value in
-                // androidVersion.)
-                antProject.setProperty(mTargetApiOut,
-                        Integer.toString(androidVersion.getApiLevel()));
-
-            } else if (value.length() > 0) {
-                // for normal platform, we'll only display warnings if the value is lower or higher
-                // than the target api level.
-                // First convert to an int.
-                int minSdkValue = -1;
-                try {
-                    minSdkValue = Integer.parseInt(value);
-                } catch (NumberFormatException e) {
-                    // looks like it's not a number: error!
-                    throw new BuildException(String.format(
-                            "Attribute %1$s in AndroidManifest.xml must be an Integer!",
-                            AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION));
-                }
-
-                // set the target api to the value
-                antProject.setProperty(mTargetApiOut, value);
-
-                int projectApiLevel = androidVersion.getApiLevel();
-                if (minSdkValue > androidVersion.getApiLevel()) {
-                    System.out.println(String.format(
-                            "WARNING: Attribute %1$s in AndroidManifest.xml (%2$d) is higher than the project target API level (%3$d)",
-                            AndroidManifest.ATTRIBUTE_MIN_SDK_VERSION,
-                            minSdkValue, projectApiLevel));
-                }
-            } else {
-                // no minSdkVersion? display a warning
-                System.out.println(
-                        "WARNING: No minSdkVersion value set. Application will install on all Android versions.");
-
-                // set the target api to 1
-                antProject.setProperty(mTargetApiOut, "1");
-            }
-
-        } catch (XPathExpressionException e) {
-            throw new BuildException(e);
-        } catch (FileNotFoundException e) {
-            throw new BuildException(e);
-        }
-    }
-
-    private void processReferencedLibraries(Project antProject, IAndroidTarget androidTarget,
-            String sdkLocation) {
-        // prepare several paths for future tasks
-        Path rootPath = new Path(antProject);
-        Path resPath = new Path(antProject);
-        Path libsPath = new Path(antProject);
-        StringBuilder packageStrBuilder = new StringBuilder();
-
-        // list of all the jars that are on the classpath. This will receive the
-        // project's libs/*.jar files, the Library Projects output and their own libs/*.jar
-        List<File> jars = new ArrayList<File>();
-
-        FilenameFilter filter = new FilenameFilter() {
-            @Override
-            public boolean accept(File dir, String name) {
-                return name.toLowerCase(Locale.US).endsWith(".jar");
-            }
-        };
-
-        System.out.println("\n------------------\nResolving library dependencies:");
-
-        // get the list of ordered libraries.
-        ArrayList<File> libraries = getProjectLibraries(antProject);
-
-        if (libraries.size() > 0) {
-            System.out.println("------------------\nOrdered libraries:");
-
-            // use that same order to return ordered res folders, as well as jars and output.
-            for (File library : libraries) {
-                // get the root path.
-                String libRootPath = library.getAbsolutePath();
-                System.out.println(libRootPath);
-
-                // get the res path. Always $PROJECT/res as well as the crunch cache.
-                PathElement element = resPath.createPathElement();
-                element.setPath(libRootPath + "/" + SdkConstants.FD_OUTPUT +
-                        "/" + SdkConstants.FD_RES);
-                element = resPath.createPathElement();
-                element.setPath(libRootPath + "/" + SdkConstants.FD_RESOURCES);
-
-                // get the libs path. Always $PROJECT/libs
-                element = libsPath.createPathElement();
-                element.setPath(libRootPath + "/" + SdkConstants.FD_NATIVE_LIBS);
-
-                // get the jars from it too.
-                // 1. the library code jar
-                jars.add(new File(libRootPath + "/" + SdkConstants.FD_OUTPUT +
-                        "/" + SdkConstants.FN_CLASSES_JAR));
-
-                // 2. the 3rd party jar files
-                File libsFolder = new File(library, SdkConstants.FD_NATIVE_LIBS);
-                File[] jarFiles = libsFolder.listFiles(filter);
-                if (jarFiles != null) {
-                    for (File jarFile : jarFiles) {
-                        jars.add(jarFile);
-                    }
-                }
-
-                // get the package from the manifest.
-                FileWrapper manifest = new FileWrapper(library,
-                        SdkConstants.FN_ANDROID_MANIFEST_XML);
-
-                try {
-                    String value = AndroidManifest.getPackage(manifest);
-                    if (value != null) { // aapt will complain if it's missing.
-                        packageStrBuilder.append(';');
-                        packageStrBuilder.append(value);
-                    }
-                } catch (Exception e) {
-                    throw new BuildException(e);
-                }
-            }
-
-            // now use the reverse order to get the full list of library project.
-            // This is used to compile all the libraries, direct or indirect dependencies,
-            // in a single pass.
-            final int count = libraries.size();
-            for (int i = count - 1 ; i >= 0 ; i--) {
-                File library = libraries.get(i);
-
-                PathElement element = rootPath.createPathElement();
-                element.setPath(library.getAbsolutePath());
-            }
-            System.out.println();
-
-        } else {
-            System.out.println("No library dependencies.\n");
-        }
-
-        System.out.println("------------------");
-
-        boolean hasLibraries = jars.size() > 0;
-
-        if (androidTarget.getVersion().getApiLevel() <= 15) {
-            System.out.println("API<=15: Adding annotations.jar to the classpath.\n");
-
-            jars.add(new File(sdkLocation + "/" + SdkConstants.FD_TOOLS +
-                    "/" + SdkConstants.FD_SUPPORT +
-                    "/" + SdkConstants.FN_ANNOTATIONS_JAR));
-
-            System.out.println("------------------");
-        }
-
-        // even with no libraries, always setup these so that various tasks in Ant don't complain
-        // (the task themselves can handle a ref to an empty Path)
-        antProject.addReference(mProjectLibrariesLibsOut, libsPath);
-
-        // the rest is done only if there's a library.
-        if (hasLibraries) {
-            antProject.addReference(mProjectLibrariesRootOut, rootPath);
-            antProject.addReference(mProjectLibrariesResOut, resPath);
-            antProject.setProperty(mProjectLibrariesPackageOut, packageStrBuilder.toString());
-        }
-
-        // add the project's own content of libs/*.jar
-        File libsFolder = new File(antProject.getBaseDir(), SdkConstants.FD_NATIVE_LIBS);
-        File[] jarFiles = libsFolder.listFiles(filter);
-        if (jarFiles != null) {
-            for (File jarFile : jarFiles) {
-                jars.add(jarFile);
-            }
-        }
-
-        // now sanitize the path to remove dups
-        jars = sanitizePaths(antProject, jars);
-
-        // and create a Path object for them
-        Path jarsPath = new Path(antProject);
-        if (mVerbose) {
-            System.out.println("Sanitized jar list:");
-        }
-        for (File f : jars) {
-            if (mVerbose) {
-                System.out.println("- " + f.getAbsolutePath());
-            }
-            PathElement element = jarsPath.createPathElement();
-            element.setPath(f.getAbsolutePath());
-        }
-        antProject.addReference(mProjectLibrariesJarsOut, jarsPath);
-
-        if (mVerbose) {
-            System.out.println();
-        }
-    }
-
-    /**
-     * Returns all the library dependencies of a given Ant project.
-     * @param antProject the Ant project
-     * @return a list of properties, sorted from highest priority to lowest.
-     */
-    private ArrayList<File> getProjectLibraries(final Project antProject) {
-        ArrayList<File> libraries = new ArrayList<File>();
-        File baseDir = antProject.getBaseDir();
-
-        // get the top level list of library dependencies.
-        List<File> topLevelLibraries = getDirectDependencies(baseDir, new IPropertySource() {
-            @Override
-            public String getProperty(String name) {
-                return antProject.getProperty(name);
-            }
-        });
-
-        // process the libraries in case they depend on other libraries.
-        resolveFullLibraryDependencies(topLevelLibraries, libraries);
-
-        return libraries;
-    }
-
-    /**
-     * Resolves a given list of libraries, finds out if they depend on other libraries, and
-     * returns a full list of all the direct and indirect dependencies in the proper order (first
-     * is higher priority when calling aapt).
-     * @param inLibraries the libraries to resolve
-     * @param outLibraries where to store all the libraries.
-     */
-    private void resolveFullLibraryDependencies(List<File> inLibraries, List<File> outLibraries) {
-        // loop in the inverse order to resolve dependencies on the libraries, so that if a library
-        // is required by two higher level libraries it can be inserted in the correct place
-        for (int i = inLibraries.size() - 1  ; i >= 0 ; i--) {
-            File library = inLibraries.get(i);
-
-            // get the default.property file for it
-            final ProjectProperties projectProp = ProjectProperties.load(
-                    new FolderWrapper(library), PropertyType.PROJECT);
-
-            // get its libraries
-            List<File> dependencies = getDirectDependencies(library, new IPropertySource() {
-                @Override
-                public String getProperty(String name) {
-                    return projectProp.getProperty(name);
-                }
-            });
-
-            // resolve the dependencies for those libraries
-            resolveFullLibraryDependencies(dependencies, outLibraries);
-
-            // and add the current one (if needed) in front (higher priority)
-            if (outLibraries.contains(library) == false) {
-                outLibraries.add(0, library);
-            }
-        }
-    }
-
-    public interface IPropertySource {
-        String getProperty(String name);
-    }
-
-    /**
-     * Returns the top level library dependencies of a given <var>source</var> representing a
-     * project properties.
-     * @param baseFolder the base folder of the project (to resolve relative paths)
-     * @param source a source of project properties.
-     */
-    private List<File> getDirectDependencies(File baseFolder, IPropertySource source) {
-        ArrayList<File> libraries = new ArrayList<File>();
-
-        // first build the list. they are ordered highest priority first.
-        int index = 1;
-        while (true) {
-            String propName = ProjectProperties.PROPERTY_LIB_REF + Integer.toString(index++);
-            String rootPath = source.getProperty(propName);
-
-            if (rootPath == null) {
-                break;
-            }
-
-            try {
-                File library = new File(baseFolder, rootPath).getCanonicalFile();
-
-                // check for validity
-                File projectProp = new File(library, PropertyType.PROJECT.getFilename());
-                if (projectProp.isFile() == false) {
-                    // error!
-                    throw new BuildException(String.format(
-                            "%1$s resolve to a path with no %2$s file for project %3$s", rootPath,
-                            PropertyType.PROJECT.getFilename(), baseFolder.getAbsolutePath()));
-                }
-
-                if (libraries.contains(library) == false) {
-                    System.out.println(String.format("%1$s: %2$s => %3$s",
-                            baseFolder.getAbsolutePath(), rootPath, library.getAbsolutePath()));
-
-                    libraries.add(library);
-                }
-            } catch (IOException e) {
-                throw new BuildException("Failed to resolve library path: " + rootPath, e);
-            }
-        }
-
-        return libraries;
-    }
-
-    /**
-     * Returns the Ant version as a {@link DeweyDecimal} object.
-     *
-     * This is based on the implementation of
-     * org.apache.tools.ant.taskdefs.condition.AntVersion.getVersion()
-     *
-     * @param antProject the current ant project.
-     * @return the ant version.
-     */
-    private DeweyDecimal getVersion(Project antProject) {
-        char[] versionString = antProject.getProperty("ant.version").toCharArray();
-        StringBuilder sb = new StringBuilder();
-        boolean foundFirstDigit = false;
-        for (int i = 0; i < versionString.length; i++) {
-            if (Character.isDigit(versionString[i])) {
-                sb.append(versionString[i]);
-                foundFirstDigit = true;
-            }
-            if (versionString[i] == '.' && foundFirstDigit) {
-                sb.append(versionString[i]);
-            }
-            if (Character.isLetter(versionString[i]) && foundFirstDigit) {
-                break;
-            }
-        }
-        return new DeweyDecimal(sb.toString());
-    }
-
-    private List<File> sanitizePaths(Project antProject, List<File> paths) {
-        // first get the non-files.
-        List<File> results = new ArrayList<File>();
-        for (int i = 0 ; i < paths.size() ;) {
-            File f = paths.get(i);
-            // TEMP WORKAROUND: ignore classes.jar as all the output of libraries are
-            // called the same (in Ant) but are not actually the same jar file.
-            // TODO: Be aware of library output vs. regular jar dependency.
-            if (f.isFile() && f.getName().equals(SdkConstants.FN_CLASSES_JAR) == false) {
-                i++;
-            } else {
-                results.add(f);
-                paths.remove(i);
-            }
-        }
-
-        File outputFile = new File(antProject.getProperty("out.absolute.dir"));
-        JarListSanitizer sanitizer = new JarListSanitizer(outputFile);
-
-        try {
-            results.addAll(sanitizer.sanitize(paths));
-        } catch (DifferentLibException e) {
-            String[] details = e.getDetails();
-            for (String s : details) {
-                System.err.println(s);
-            }
-            throw new BuildException(e.getMessage(), e);
-        } catch (Sha1Exception e) {
-            throw new BuildException(
-                    "Failed to compute sha1 for " + e.getJarFile().getAbsolutePath(), e);
-        }
-
-        return results;
-    }
-}
diff --git a/anttasks/src/com/android/ant/RenderScriptTask.java b/anttasks/src/com/android/ant/RenderScriptTask.java
index 937ceac..b64a731 100644
--- a/anttasks/src/com/android/ant/RenderScriptTask.java
+++ b/anttasks/src/com/android/ant/RenderScriptTask.java
@@ -43,7 +43,7 @@
 public class RenderScriptTask extends MultiFilesTask {
 
     private String mExecutable;
-    private Path mFramework;
+    private Path mIncludePath;
     private String mGenFolder;
     private String mResFolder;
     private final List<Path> mPaths = new ArrayList<Path>();
@@ -79,7 +79,7 @@
             task.setExecutable(mExecutable);
             task.setFailonerror(true);
 
-            for (String path : mFramework.list()) {
+            for (String path : mIncludePath.list()) {
                 File res = new File(path);
                 if (res.isDirectory()) {
                     task.createArg().setValue("-I");
@@ -163,8 +163,8 @@
         mExecutable = TaskHelper.checkSinglePath("executable", executable);
     }
 
-    public void setFramework(Path value) {
-        mFramework = value;
+    public void setIncludePath(Path value) {
+        mIncludePath = value;
     }
 
     public void setGenFolder(Path value) {
@@ -208,8 +208,8 @@
         if (mExecutable == null) {
             throw new BuildException("RenderScriptTask's 'executable' is required.");
         }
-        if (mFramework == null) {
-            throw new BuildException("RenderScriptTask's 'framework' is required.");
+        if (mIncludePath == null) {
+            throw new BuildException("RenderScriptTask's 'includePath' is required.");
         }
         if (mGenFolder == null) {
             throw new BuildException("RenderScriptTask's 'genFolder' is required.");
diff --git a/anttasks/src/com/android/ant/SetupTask.java b/anttasks/src/com/android/ant/SetupTask.java
deleted file mode 100644
index c0bc55d..0000000
--- a/anttasks/src/com/android/ant/SetupTask.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.ant;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.taskdefs.ImportTask;
-
-/**
- * Legacy setupTask class used by older build system.
- *
- * If this is used it actually only display an error about the need to update the build file.
- */
-public final class SetupTask extends Task {
-
-    /**
-     * @param b unused.
-     *
-     * @deprecated only present because the original {@link SetupTask} extends {@link ImportTask}.
-     */
-    @Deprecated
-    public void setImport(boolean b) {
-        // do nothing
-    }
-
-    @Override
-    public void execute() throws BuildException {
-        throw new BuildException("\n\nError. You are using an obsolete build.xml\n" +
-                "You need to delete it and regenerate it using\n" +
-                "\tandroid update project\n");
-    }
-}
diff --git a/changes.txt b/changes.txt
index d60be8e..67f6cf2 100644
--- a/changes.txt
+++ b/changes.txt
@@ -1,6 +1,14 @@
 Change log for Android SDK Tools.
 
+Revision 20:
+- Ant build system:
+   * the location of the SDK can now be set through the ANDROID_HOME
+     environment variable (requires updating the project's build.xml file)
+   * Fixed issues with compilation, deployment of test projects and running tests.
+     Both separate test projects and self-contained app+test projects now work.
+
 Revision 19:
+- Fix GPU rendering
 
 Revision 18:
 * Fix Ant issues where some jar libraries in libs/ are not picked in some
diff --git a/eclipse/features/com.android.ide.eclipse.adt/feature.xml b/eclipse/features/com.android.ide.eclipse.adt/feature.xml
index 0e631d6..b99ecea 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="19.0.0.qualifier"
+      version="20.0.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 b8593cf..848ef09 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="19.0.0.qualifier"
+      version="20.0.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 839fc00..ea82d50 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="GLESv2 Debugger Client"
-      version="19.0.0.qualifier"
+      version="20.0.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 1e55a81..207be3a 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="19.0.0.qualifier"
+      version="20.0.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 af9ddbc..ac13960 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="19.0.0.qualifier"
+      version="20.0.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 378e1aa..3874bb5 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="19.0.0.qualifier"
+      version="20.0.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 93e1bcb..3341780 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="19.0.0.qualifier"
+      version="20.0.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 4acf8b5..4ffd529 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="19.0.0.qualifier"
+      version="20.0.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 734e8e1..63581ed 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: ADT XML Overlay
 Bundle-SymbolicName: overlay.com.android.ide.eclipse.adt.overlay;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.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/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index 9388d69..3de6944 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Android Development Toolkit
 Bundle-SymbolicName: com.android.ide.eclipse.adt;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.0.qualifier
 Bundle-ClassPath: .,
  libs/sdkuilib.jar,
  libs/ninepatch.jar,
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
index 9c73e1c..e08bfc1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gre/ClientRulesEngine.java
@@ -248,56 +248,9 @@
 
     private String displayResourceInput(String resourceTypeName, String currentValue,
             IInputValidator validator) {
-        GraphicalEditorPart graphicalEditor = mRulesEngine.getEditor();
-        AndroidXmlEditor editor = graphicalEditor.getEditorDelegate().getEditor();
-        IProject project = editor.getProject();
         ResourceType type = ResourceType.getEnum(resourceTypeName);
-        if (project != null) {
-            // get the resource repository for this project and the system resources.
-            ResourceRepository projectRepository = ResourceManager.getInstance()
-                    .getProjectResources(project);
-            Shell shell = AdtPlugin.getDisplay().getActiveShell();
-            if (shell == null) {
-                return null;
-            }
-
-            AndroidTargetData data = editor.getTargetData();
-            ResourceRepository systemRepository = data.getFrameworkResources();
-
-            // open a resource chooser dialog for specified resource type.
-            ResourceChooser dlg = new ResourceChooser(project, type, projectRepository,
-                    systemRepository, shell);
-            dlg.setPreviewHelper(new ResourcePreviewHelper(dlg, graphicalEditor));
-
-            // When editing Strings, allow editing the value text directly. When we
-            // get inline editing support (where values entered directly into the
-            // textual widget are translated automatically into a resource) this can
-            // go away.
-            if (resourceTypeName.equals(ResourceType.STRING.getName())) {
-                dlg.setResourceResolver(graphicalEditor.getResourceResolver());
-                dlg.setShowValueText(true);
-            } else if (resourceTypeName.equals(ResourceType.DIMEN.getName())
-                    || resourceTypeName.equals(ResourceType.INTEGER.getName())) {
-                dlg.setResourceResolver(graphicalEditor.getResourceResolver());
-            }
-
-            if (validator != null) {
-                // Ensure wide enough to accommodate validator error message
-                dlg.setSize(85, 10);
-                dlg.setInputValidator(validator);
-            }
-
-            dlg.setCurrentResource(currentValue);
-
-            int result = dlg.open();
-            if (result == ResourceChooser.CLEAR_RETURN_CODE) {
-                return ""; //$NON-NLS-1$
-            } else if (result == Window.OK) {
-                return dlg.getCurrentResource();
-            }
-        }
-
-        return null;
+        GraphicalEditorPart graphicalEditor = mRulesEngine.getEditor();
+        return ResourceChooser.chooseResource(graphicalEditor, type, currentValue, validator);
     }
 
     @Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
index 202e1cf..7b90633 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/ui/ResourceChooser.java
@@ -28,11 +28,14 @@
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.AdtUtils;
 import com.android.ide.eclipse.adt.internal.assetstudio.OpenCreateAssetSetWizardAction;
+import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
 import com.android.ide.eclipse.adt.internal.editors.layout.gle2.GraphicalEditorPart;
 import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringRefactoring;
 import com.android.ide.eclipse.adt.internal.refactorings.extractstring.ExtractStringWizard;
 import com.android.ide.eclipse.adt.internal.resources.ResourceHelper;
 import com.android.ide.eclipse.adt.internal.resources.ResourceNameValidator;
+import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager;
+import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData;
 import com.android.resources.ResourceType;
 import com.android.util.Pair;
 
@@ -790,6 +793,52 @@
             @NonNull GraphicalEditorPart graphicalEditor,
             @NonNull ResourceType type,
             String currentValue, IInputValidator validator) {
-        return ResourceChooser.chooseResource(graphicalEditor, type, currentValue, validator);
+        AndroidXmlEditor editor = graphicalEditor.getEditorDelegate().getEditor();
+        IProject project = editor.getProject();
+        if (project != null) {
+            // get the resource repository for this project and the system resources.
+            ResourceRepository projectRepository = ResourceManager.getInstance()
+                    .getProjectResources(project);
+            Shell shell = AdtPlugin.getDisplay().getActiveShell();
+            if (shell == null) {
+                return null;
+            }
+
+            AndroidTargetData data = editor.getTargetData();
+            ResourceRepository systemRepository = data.getFrameworkResources();
+
+            // open a resource chooser dialog for specified resource type.
+            ResourceChooser dlg = new ResourceChooser(project, type, projectRepository,
+                    systemRepository, shell);
+            dlg.setPreviewHelper(new ResourcePreviewHelper(dlg, graphicalEditor));
+
+            // When editing Strings, allow editing the value text directly. When we
+            // get inline editing support (where values entered directly into the
+            // textual widget are translated automatically into a resource) this can
+            // go away.
+            if (type == ResourceType.STRING) {
+                dlg.setResourceResolver(graphicalEditor.getResourceResolver());
+                dlg.setShowValueText(true);
+            } else if (type == ResourceType.DIMEN || type == ResourceType.INTEGER) {
+                dlg.setResourceResolver(graphicalEditor.getResourceResolver());
+            }
+
+            if (validator != null) {
+                // Ensure wide enough to accommodate validator error message
+                dlg.setSize(85, 10);
+                dlg.setInputValidator(validator);
+            }
+
+            dlg.setCurrentResource(currentValue);
+
+            int result = dlg.open();
+            if (result == ResourceChooser.CLEAR_RETURN_CODE) {
+                return ""; //$NON-NLS-1$
+            } else if (result == Window.OK) {
+                return dlg.getCurrentResource();
+            }
+        }
+
+        return null;
     }
 }
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 ba15622..461335b 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Common Android Utilities
 Bundle-SymbolicName: com.android.ide.eclipse.base;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.0.qualifier
 Bundle-Activator: com.android.ide.eclipse.base.BasePlugin
 Require-Bundle: org.eclipse.ui,
  org.eclipse.core.runtime
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 47c8265..66f7cc5 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: com.android.ide.eclipse.ddms;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.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.gldebugger.tests/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.gldebugger.tests/META-INF/MANIFEST.MF
index daab531..d0ac20a 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: gldebugger-tests
 Bundle-SymbolicName: com.android.ide.eclipse.gldebugger.tests
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.0.qualifier
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Require-Bundle: org.junit4;bundle-version="4.5.0",
  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 cbd95da..b6404ca 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: GLESv2 Debugger Client
 Bundle-SymbolicName: com.android.ide.eclipse.gldebugger;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.0.qualifier
 Bundle-Activator: com.android.ide.eclipse.gldebugger.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 b7b284a..e297aa1 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Hierarchy Viewer
 Bundle-SymbolicName: com.android.ide.eclipse.hierarchyviewer;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.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 b0ffa36..9635997 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %Bundle-Name
 Bundle-SymbolicName: com.android.ide.eclipse.monitor;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.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 f627a13..c7323fb 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="19.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="20.0.0" useFeatures="false" includeLaunchers="true">
 
    <configIni use="default">
    </configIni>
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 ed475d5..1180cf3 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: ADT CDT Integration
 Bundle-SymbolicName: com.android.ide.eclipse.ndk;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.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.pdt/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.pdt/META-INF/MANIFEST.MF
index 0ecba08..bbe325d 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 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Pdt
 Bundle-SymbolicName: com.android.ide.eclipse.pdt;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.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 aa76ddf..4caab63 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,9 +2,9 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Android Plugin Tests
 Bundle-SymbolicName: com.android.ide.eclipse.tests
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.0.qualifier
 Bundle-Vendor: The Android Open Source Project
-Fragment-Host: com.android.ide.eclipse.adt;bundle-version="19.0.0"
+Fragment-Host: com.android.ide.eclipse.adt;bundle-version="20.0.0"
 Require-Bundle: org.junit
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Bundle-ClassPath: kxml2-2.3.0.jar,
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 f047c0b..1e02be9 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,12 +2,12 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: Traceview
 Bundle-SymbolicName: com.android.ide.eclipse.traceview;singleton:=true
-Bundle-Version: 19.0.0.qualifier
+Bundle-Version: 20.0.0.qualifier
 Bundle-Activator: com.android.ide.eclipse.traceview.TraceviewPlugin
 Require-Bundle: org.eclipse.ui,
  org.eclipse.core.runtime,
  org.eclipse.ui.ide,
- com.android.ide.eclipse.ddms;bundle-version="19.0.0",
+ com.android.ide.eclipse.ddms;bundle-version="20.0.0",
  org.eclipse.core.filesystem,
  org.eclipse.core.resources
 Bundle-ActivationPolicy: lazy
diff --git a/eclipse/sites/external/site.xml b/eclipse/sites/external/site.xml
index a2ae630..ce81437 100644
--- a/eclipse/sites/external/site.xml
+++ b/eclipse/sites/external/site.xml
@@ -3,19 +3,19 @@
    <description url="https://dl-ssl.google.com/android/eclipse/">
       Update Site for Android Development Toolkit
    </description>
-   <feature url="features/com.android.ide.eclipse.adt_19.0.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.adt_20.0.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="20.0.0.qualifier">
       <category name="developer"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.ddms_19.0.0.qualifier.jar" id="com.android.ide.eclipse.ddms" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.ddms_20.0.0.qualifier.jar" id="com.android.ide.eclipse.ddms" version="20.0.0.qualifier">
       <category name="developer"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.hierarchyviewer_19.0.0.qualifier.jar" id="com.android.ide.eclipse.hierarchyviewer" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.hierarchyviewer_20.0.0.qualifier.jar" id="com.android.ide.eclipse.hierarchyviewer" version="20.0.0.qualifier">
       <category name="developer"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.traceview_19.0.0.qualifier.jar" id="com.android.ide.eclipse.traceview" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.traceview_20.0.0.qualifier.jar" id="com.android.ide.eclipse.traceview" version="20.0.0.qualifier">
       <category name="developer"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.ndk_19.0.0.qualifier.jar" id="com.android.ide.eclipse.ndk" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.ndk_20.0.0.qualifier.jar" id="com.android.ide.eclipse.ndk" version="20.0.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 4d83e8b..8bea717 100644
--- a/eclipse/sites/internal/site.xml
+++ b/eclipse/sites/internal/site.xml
@@ -3,31 +3,31 @@
    <description url="https://android.corp.google.com/adt/">
       Update Site for Android Development Toolkit
    </description>
-   <feature url="features/com.android.ide.eclipse.adt_19.0.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.adt_20.0.0.qualifier.jar" id="com.android.ide.eclipse.adt" version="20.0.0.qualifier">
       <category name="developer"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.ddms_19.0.0.qualifier.jar" id="com.android.ide.eclipse.ddms" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.ddms_20.0.0.qualifier.jar" id="com.android.ide.eclipse.ddms" version="20.0.0.qualifier">
       <category name="developer"/>
       <category name="platform"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.hierarchyviewer_19.0.0.qualifier.jar" id="com.android.ide.eclipse.hierarchyviewer" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.hierarchyviewer_20.0.0.qualifier.jar" id="com.android.ide.eclipse.hierarchyviewer" version="20.0.0.qualifier">
       <category name="developer"/>
       <category name="platform"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.tests_19.0.0.qualifier.jar" id="com.android.ide.eclipse.tests" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.tests_20.0.0.qualifier.jar" id="com.android.ide.eclipse.tests" version="20.0.0.qualifier">
       <category name="test"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.pdt_19.0.0.qualifier.jar" id="com.android.ide.eclipse.pdt" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.pdt_20.0.0.qualifier.jar" id="com.android.ide.eclipse.pdt" version="20.0.0.qualifier">
       <category name="platform"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.traceview_19.0.0.qualifier.jar" id="com.android.ide.eclipse.traceview" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.traceview_20.0.0.qualifier.jar" id="com.android.ide.eclipse.traceview" version="20.0.0.qualifier">
       <category name="developer"/>
       <category name="platform"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.gldebugger_19.0.0.qualifier.jar" id="com.android.ide.eclipse.gldebugger" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.gldebugger_20.0.0.qualifier.jar" id="com.android.ide.eclipse.gldebugger" version="20.0.0.qualifier">
       <category name="preview"/>
    </feature>
-   <feature url="features/com.android.ide.eclipse.ndk_19.0.0.qualifier.jar" id="com.android.ide.eclipse.ndk" version="19.0.0.qualifier">
+   <feature url="features/com.android.ide.eclipse.ndk_20.0.0.qualifier.jar" id="com.android.ide.eclipse.ndk" version="20.0.0.qualifier">
       <category name="preview"/>
    </feature>
    <category-def name="developer" label="Application Developer Tools">
diff --git a/files/ant/build.xml b/files/ant/build.xml
index 7d2a6d7..db47263 100644
--- a/files/ant/build.xml
+++ b/files/ant/build.xml
@@ -27,7 +27,7 @@
     <!-- **************** Overridable Properties *************** -->
     <!-- ******************************************************* -->
 
-    <!-- You can override these values in your build.xml or build.properties.
+    <!-- You can override these values in your build.xml or ant.properties.
          Overriding any other properties may result in broken build. -->
 
     <!-- Tells adb which device to target. You can change this from the command line
@@ -72,8 +72,32 @@
     </path>
 
     <!-- Custom tasks -->
-    <taskdef name="setup"
-            classname="com.android.ant.NewSetupTask"
+    <taskdef name="checkenv"
+            classname="com.android.ant.CheckEnvTask"
+            classpathref="android.antlibs" />
+
+    <taskdef name="gettype"
+            classname="com.android.ant.GetTypeTask"
+            classpathref="android.antlibs" />
+
+    <taskdef name="gettarget"
+            classname="com.android.ant.GetTargetTask"
+            classpathref="android.antlibs" />
+
+    <taskdef name="getlibs"
+            classname="com.android.ant.GetLibraryListTask"
+            classpathref="android.antlibs" />
+
+    <taskdef name="dependency"
+            classname="com.android.ant.ComputeDependencyTask"
+            classpathref="android.antlibs" />
+
+    <taskdef name="testedprojectclasspath"
+            classname="com.android.ant.ComputeProjectClasspathTask"
+            classpathref="android.antlibs" />
+
+    <taskdef name="getemmafilter"
+            classname="com.android.ant.GetEmmaFilterTask"
             classpathref="android.antlibs" />
 
     <taskdef name="aapt"
@@ -163,8 +187,13 @@
     <property name="aidl" location="${android.platform.tools.dir}/aidl${exe}" />
     <property name="aapt" location="${android.platform.tools.dir}/aapt${exe}" />
     <property name="dx" location="${android.platform.tools.dir}/dx${bat}" />
-    <!-- renderscript location is set by NewSetupTask since we have a choice of
-         several executables based on minSdkVersion -->
+    <property name="renderscript" location="${android.platform.tools.dir}/llvm-rs-cc${exe}"/>
+
+    <!-- Renderscript include Path -->
+    <path id="android.renderscript.include.path">
+        <pathelement location="${android.platform.tools.dir}/renderscript/include" />
+        <pathelement location="${android.platform.tools.dir}/renderscript/clang-include" />
+    </path>
 
     <!-- Intermediate files -->
     <property name="dex.file.name" value="classes.dex" />
@@ -276,7 +305,7 @@
                 </condition>
                 <else>
                     <path id="out.dex.jar.input.ref">
-                        <path refid="project.libraries.jars" />
+                        <path refid="project.all.jars.path" />
                     </path>
                 </else>
             </if>
@@ -316,9 +345,9 @@
                     buildType="${build.is.packaging.debug}/${build.is.signing.debug}">
                 <dex path="${intermediate.dex.file}"/>
                 <sourcefolder path="${source.absolute.dir}"/>
-                <jarfile refid="project.libraries.jars" />
+                <jarfile refid="project.all.jars.path" />
                 <nativefolder path="${native.libs.absolute.dir}" />
-                <nativefolder refid="project.libraries.libs" />
+                <nativefolder refid="project.library.native.folder.path" />
                 <extra-jars/>
             </apkbuilder>
         </sequential>
@@ -353,7 +382,7 @@
                 <arg value="coverage" />
                 <arg value="@{emma.enabled}" />
                 <extra-instrument-args />
-                <arg value="${manifest.package}/${test.runner}" />
+                <arg value="${project.app.package}/${test.runner}" />
             </exec>
         </sequential>
     </macrodef>
@@ -393,104 +422,86 @@
     <!-- ******************** Build Targets ******************** -->
     <!-- ******************************************************* -->
 
+    <!-- Basic Ant + SDK check -->
+    <target name="-check-env">
+        <checkenv />
+    </target>
+
     <!-- target to disable building dependencies -->
     <target name="nodeps">
         <property name="dont.do.deps" value="true" />
     </target>
 
-    <!-- this target simply force running -setup making
-         the project info be read. To be used as
-             ant all clean
-         to clean the main project as well as the libraries and tested project -->
-    <target name="all" depends="-setup"/>
+    <!-- generic setup -->
+    <target name="-setup" depends="-check-env">
+        <echo level="info">Project Name: ${ant.project.name}</echo>
+        <gettype projectTypeOut="project.type" />
+
+        <!-- sets a few boolean based on project.type
+             to make the if task easier -->
+        <condition property="project.is.library" value="true" else="false">
+            <equals arg1="${project.type}" arg2="library" />
+        </condition>
+        <condition property="project.is.test" value="true" else="false">
+            <equals arg1="${project.type}" arg2="test" />
+        </condition>
+        <condition property="project.is.testapp" value="true" else="false">
+            <equals arg1="${project.type}" arg2="test-app" />
+        </condition>
+
+        <!-- If a test project, resolve absolute path to tested project. -->
+        <if condition="${project.is.test}">
+            <then>
+                <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
+            </then>
+        </if>
+
+        <!-- get the project manifest package -->
+        <xpath input="AndroidManifest.xml"
+                expression="/manifest/@package" output="project.app.package" />
+
+    </target>
 
     <!-- empty default pre-clean target. Create a similar target in
          your build.xml and it'll be called instead of this one. -->
     <target name="-pre-clean"/>
 
     <!-- clean target -->
-    <target name="clean" depends="-pre-clean"
+    <target name="clean" depends="-setup, -pre-clean"
             description="Removes output files created by other targets.">
         <delete dir="${out.absolute.dir}" verbose="${verbose}" />
         <delete dir="${gen.absolute.dir}" verbose="${verbose}" />
 
-        <!-- if we know about a tested project or libraries, we clean them too. This
-             will only work if the target 'all' was called first -->
+        <!-- if we know about a tested project or libraries, we clean them too. -->
         <if condition="${project.is.test}">
             <then>
                 <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
                 <subant failonerror="true">
                     <fileset dir="${tested.project.absolute.dir}" includes="build.xml" />
-                    <target name="all" />
                     <target name="clean" />
                 </subant>
             </then>
         </if>
 
+        <!-- get all the libraries -->
         <if>
-            <condition>
-                <isreference refid="project.libraries" />
-                <not><isset property="dont.do.deps" /></not>
-            </condition>
+            <condition><not><isset property="dont.do.deps" /></not></condition>
             <then>
-                <subant
-                        buildpathref="project.libraries"
-                        antfile="build.xml"
-                        failonerror="true">
-                    <target name="nodeps" />
-                    <target name="clean" />
-                </subant>
-            </then>
-        </if>
-    </target>
-
-    <!-- generic setup -->
-    <target name="-setup">
-        <if>
-            <condition>
-                <not><isset property="setup.done" /></not>
-            </condition>
-            <then>
-                <echo level="info">Creating output directories if needed...</echo>
-                <mkdir dir="${resource.absolute.dir}" />
-                <mkdir dir="${jar.libs.absolute.dir}" />
-                <mkdir dir="${out.absolute.dir}" />
-                <mkdir dir="${out.res.absolute.dir}" />
-
-                <property name="setup.done" value="true" />
-                <echo level="info">Gathering info for ${ant.project.name}...</echo>
-                <!-- load project properties, resolve Android target, library dependencies
-                     and set some properties with the results.
-                     All property names are passed as parameters ending in -Out -->
-                <setup
-                        projectTypeOut="android.project.type"
-                        androidJarFileOut="android.jar"
-                        androidAidlFileOut="android.aidl"
-                        renderScriptExeOut="renderscript"
-                        renderScriptIncludeDirOut="android.rs"
-                        bootclasspathrefOut="android.target.classpath"
-                        projectLibrariesRootOut="project.libraries"
-                        projectLibrariesJarsOut="project.libraries.jars"
-                        projectLibrariesResOut="project.libraries.res"
-                        projectLibrariesPackageOut="project.libraries.package"
-                        projectLibrariesLibsOut="project.libraries.libs"
-                        targetApiOut="target.api"
-                        verbose="${verbose}"
-                />
-
-                <!-- sets a few boolean based on android.project.type
-                     to make the if task easier -->
-                <condition property="project.is.library" else="false">
-                    <equals arg1="${android.project.type}" arg2="library" />
-                </condition>
-                <condition property="project.is.test" else="false">
-                    <equals arg1="${android.project.type}" arg2="test" />
-                </condition>
-
-                <!-- If a test project, resolve absolute path to tested project. -->
-                <if condition="${project.is.test}">
+                <getlibs libraryFolderPathOut="project.library.folder.path" />
+                <if>
+                    <condition>
+                        <isreference refid="project.library.folder.path" />
+                    </condition>
                     <then>
-                        <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
+                        <!-- clean the libraries with nodeps since we already
+                             know about all the libraries even the indirect one -->
+                        <subant
+                                buildpathref="project.library.folder.path"
+                                antfile="build.xml"
+                                failonerror="true">
+                            <target name="nodeps" />
+                            <target name="clean" />
+                        </subant>
                     </then>
                 </if>
             </then>
@@ -509,26 +520,69 @@
         <property name="build.last.is.packaging.debug" value="" />
         <property name="build.last.is.signing.debug" value="" />
 
+        <echo level="info">Resolving Build Target for ${ant.project.name}...</echo>
+        <!-- load project properties, resolve Android target, library dependencies
+             and set some properties with the results.
+             All property names are passed as parameters ending in -Out -->
+        <gettarget
+                androidJarFileOut="project.target.android.jar"
+                androidAidlFileOut="project.target.framework.aidl"
+                bootClassPathOut="project.target.class.path"
+                targetApiOut="project.target.apilevel"
+                minSdkVersionOut="project.minSdkVersion" />
+
+        <!-- Value of the hasCode attribute (Application node) extracted from manifest file -->
+        <xpath input="AndroidManifest.xml" expression="/manifest/application/@android:hasCode"
+                    output="manifest.hasCode" default="true"/>
+
+        <echo level="info">----------</echo>
+        <echo level="info">Creating output directories if needed...</echo>
+        <mkdir dir="${resource.absolute.dir}" />
+        <mkdir dir="${jar.libs.absolute.dir}" />
+        <mkdir dir="${out.absolute.dir}" />
+        <mkdir dir="${out.res.absolute.dir}" />
+        <do-only-if-manifest-hasCode>
+            <mkdir dir="${gen.absolute.dir}" />
+            <mkdir dir="${out.classes.absolute.dir}" />
+        </do-only-if-manifest-hasCode>
+
+        <echo level="info">----------</echo>
+        <echo level="info">Resolving Dependencies for ${ant.project.name}...</echo>
+        <dependency
+                libraryFolderPathOut="project.library.folder.path"
+                libraryPackagesOut="project.library.packages"
+                libraryResFolderPathOut="project.library.res.folder.path"
+                libraryNativeFolderPathOut="project.library.native.folder.path"
+                jarLibraryPathOut="project.all.jars.path"
+                targetApi="${project.target.apilevel}"
+                verbose="${verbose}" />
+
         <!-- compile the libraries if any -->
         <if>
             <condition>
                 <and>
-                    <isreference refid="project.libraries" />
+                    <isreference refid="project.library.folder.path" />
                     <not><isset property="dont.do.deps" /></not>
                 </and>
             </condition>
             <then>
-                <echo level="info">Building Libraries</echo>
+                <!-- figure out which target must be used to build the library projects.
+                     If emma is enabled, then use 'instrument' otherwise, use 'debug' -->
+                <condition property="project.libraries.target" value="instrument" else="${build.target}">
+                    <istrue value="${build.is.instrumented}" />
+                </condition>
+
+                <echo level="info">----------</echo>
+                <echo level="info">Building Libraries with '${project.libraries.target}'...</echo>
+
+                <!-- no need to build the deps as we have already
+                     the full list of libraries -->
                 <subant failonerror="true"
-                        buildpathref="project.libraries"
+                        buildpathref="project.library.folder.path"
                         antfile="build.xml">
                     <target name="nodeps" />
-                    <target name="${build.target}" />
+                    <target name="${project.libraries.target}" />
                 </subant>
-                <echo level="info"></echo>
-                <echo level="info">############################################</echo>
-                <echo level="info">**** Back to project ${ant.project.name} ****</echo>
-                <echo level="info">############################################</echo>
             </then>
         </if>
 
@@ -541,20 +595,25 @@
                     <isset property="emma.enabled" />
                 </condition>
 
-                <echo level="info">Building tested project at ${tested.project.absolute.dir}</echo>
+                <echo level="info">----------</echo>
+                <echo level="info">Building tested project at ${tested.project.absolute.dir} with '${tested.project.target}'...</echo>
                 <subant target="${tested.project.target}" failonerror="true">
                     <fileset dir="${tested.project.absolute.dir}" includes="build.xml" />
                 </subant>
-                <echo level="info"></echo>
-                <echo level="info">############################################</echo>
-                <echo level="info">**** Back to project ${ant.project.name} ****</echo>
-                <echo level="info">############################################</echo>
+
+                <!-- get the tested project full classpath to be able to build
+                     the test project -->
+                <testedprojectclasspath
+                        projectLocation="${tested.project.absolute.dir}"
+                        projectClassPathOut="tested.project.classpath"/>
             </then>
+            <else>
+                <!-- no tested project, make an empty Path object so that javac doesn't
+                     complain -->
+                <path id="tested.project.classpath" />
+            </else>
         </if>
 
-        <!-- Value of the hasCode attribute (Application node) extracted from manifest file -->
-        <xpath input="AndroidManifest.xml" expression="/manifest/application/@android:hasCode"
-                    output="manifest.hasCode" default="true"/>
 
         <!-- If the "debug" build type changed, clear out the compiled code.
              This is to make sure the new BuildConfig.DEBUG value is picked up
@@ -590,11 +649,6 @@
                 </if>
             </else>
         </if>
-
-        <do-only-if-manifest-hasCode>
-            <mkdir dir="${gen.absolute.dir}" />
-            <mkdir dir="${out.classes.absolute.dir}" />
-        </do-only-if-manifest-hasCode>
     </target>
 
     <!-- empty default pre-build target. Create a similar target in
@@ -605,9 +659,8 @@
     <target name="-code-gen">
         <do-only-if-manifest-hasCode
                 elseText="hasCode = false. Skipping aidl/renderscript/R.java">
-            <echo level="info">----------</echo>
             <echo level="info">Handling aidl files...</echo>
-            <aidl executable="${aidl}" framework="${android.aidl}"
+            <aidl executable="${aidl}" framework="${project.target.framework.aidl}"
                     genFolder="${gen.absolute.dir}">
                 <source path="${source.absolute.dir}"/>
             </aidl>
@@ -616,10 +669,10 @@
             <echo level="info">----------</echo>
             <echo level="info">Handling RenderScript files...</echo>
             <renderscript executable="${renderscript}"
-                    framework="${android.rs}"
+                    includePath="${android.renderscript.include.path}"
                     genFolder="${gen.absolute.dir}"
                     resFolder="${out.res.absolute.dir}/raw"
-                    targetApi="${target.api}"
+                    targetApi="${project.minSdkVersion}"
                     optLevel="${renderscript.opt.level}"
                     buildType="${build.is.packaging.debug}"
                     previousBuildType="${build.last.is.packaging.debug}">
@@ -632,22 +685,20 @@
                     command="package"
                     verbose="${verbose}"
                     manifest="AndroidManifest.xml"
-                    androidjar="${android.jar}"
+                    androidjar="${project.target.android.jar}"
                     rfolder="${gen.absolute.dir}"
                     nonConstantId="${android.library}"
-                    projectLibrariesResName="project.libraries.res"
-                    projectLibrariesPackageName="project.libraries.package">
+                    libraryResFolderPathRefid="project.library.res.folder.path"
+                    libraryPackagesRefid="project.library.packages">
                 <res path="${out.res.absolute.dir}" />
                 <res path="${resource.absolute.dir}" />
             </aapt>
 
             <echo level="info">----------</echo>
             <echo level="info">Handling BuildConfig class...</echo>
-            <xpath input="AndroidManifest.xml" expression="/manifest/@package"
-                    output="manifest.package" />
             <buildconfig
                     genFolder="${gen.absolute.dir}"
-                    package="${manifest.package}"
+                    package="${project.app.package}"
                     buildType="${build.is.packaging.debug}"
                     previousBuildType="${build.last.is.packaging.debug}"/>
 
@@ -661,34 +712,48 @@
     <!-- Compiles this project's .java files into .class files. -->
     <target name="-compile" depends="-build-setup, -pre-build, -code-gen, -pre-compile">
         <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping...">
-            <!-- If android rules are used for a test project, its classpath should include
-                 tested project's location -->
-            <condition property="extensible.classpath"
-                    value="${tested.project.absolute.dir}/bin/classes"
-                    else=".">
-                <isset property="tested.project.absolute.dir" />
-            </condition>
-            <condition property="extensible.libs.classpath"
-                    value="${tested.project.absolute.dir}/${jar.libs.dir}"
-                    else="${jar.libs.dir}">
-                <isset property="tested.project.absolute.dir" />
-            </condition>
+            <!-- merge the project's own classpath and the tested project's classpath -->
+            <path id="project.javac.classpath">
+                <path refid="project.all.jars.path" />
+                <path refid="tested.project.classpath" />
+            </path>
             <javac encoding="${java.encoding}"
                     source="${java.source}" target="${java.target}"
                     debug="true" extdirs="" includeantruntime="false"
                     destdir="${out.classes.absolute.dir}"
-                    bootclasspathref="android.target.classpath"
+                    bootclasspathref="project.target.class.path"
                     verbose="${verbose}"
-                    classpath="${extensible.classpath}"
-                    classpathref="project.libraries.jars"
+                    classpathref="project.javac.classpath"
                     fork="${need.javac.fork}">
                 <src path="${source.absolute.dir}" />
                 <src path="${gen.absolute.dir}" />
-                <classpath>
-                    <fileset dir="${extensible.libs.classpath}" includes="*.jar" />
-                </classpath>
                 <compilerarg line="${java.compilerargs}" />
             </javac>
+
+            <!-- if the project is instrumented, intrument the classes -->
+            <if condition="${build.is.instrumented}">
+                <then>
+                    <echo level="info">Instrumenting classes from ${out.absolute.dir}/classes...</echo>
+
+                    <!-- build the filter to remove R, Manifest, BuildConfig -->
+                    <getemmafilter
+                            appPackage="${project.app.package}"
+                            libraryPackagesRefId="project.library.packages"
+                            filterOut="emma.default.filter"/>
+
+                    <!-- It only instruments class files, not any external libs -->
+                    <emma enabled="true">
+                        <instr verbosity="${verbosity}"
+                               mode="overwrite"
+                               instrpath="${out.absolute.dir}/classes"
+                               outdir="${out.absolute.dir}/classes">
+                            <filter excludes="${emma.default.filter}" />
+                            <filter value="${emma.filter}" />
+                        </instr>
+                    </emma>
+                </then>
+            </if>
+
             <!-- if the project is a library then we generate a jar file -->
             <if condition="${project.is.library}">
                 <then>
@@ -703,33 +768,17 @@
                         </then>
                     </if>
 
-                    <propertybyreplace name="manifest.package.path" input="${manifest.package}" replace="." with="/" />
+                    <propertybyreplace name="project.app.package.path" input="${project.app.package}" replace="." with="/" />
 
                     <jar destfile="${out.library.jar.file}">
                         <fileset dir="${out.classes.absolute.dir}"
                                 includes="**/*.class"
-                                excludes="${manifest.package.path}/R.class ${manifest.package.path}/R$*.class ${manifest.package.path}/Manifest.class ${manifest.package.path}/Manifest$*.class ${manifest.package.path}/BuildConfig.class"/>
+                                excludes="${project.app.package.path}/R.class ${project.app.package.path}/R$*.class ${project.app.package.path}/Manifest.class ${project.app.package.path}/Manifest$*.class ${project.app.package.path}/BuildConfig.class"/>
                         <fileset dir="${source.absolute.dir}" excludes="**/*.java ${android.package.excludes}" />
                     </jar>
                 </then>
             </if>
 
-            <!-- if the project is instrumented, intrument the classes -->
-            <if condition="${build.is.instrumented}">
-                <then>
-                    <echo level="info">Instrumenting classes from ${out.absolute.dir}/classes...</echo>
-                    <!-- It only instruments class files, not any external libs -->
-                    <emma enabled="true">
-                        <instr verbosity="${verbosity}"
-                               mode="overwrite"
-                               instrpath="${out.absolute.dir}/classes"
-                               outdir="${out.absolute.dir}/classes">
-                            <filter excludes="${manifest.package}.R,${manifest.package}.R$$*,${manifest.package}.BuildConfig" />
-                            <filter value="${emma.filter}" />
-                        </instr>
-                    </emma>
-                </then>
-            </if>
         </do-only-if-manifest-hasCode>
     </target>
 
@@ -770,7 +819,7 @@
                      all the jar files separated by a platform path-separator.
                      Each path must be quoted if it contains spaces.
                 -->
-                <pathconvert property="android.libraryjars" refid="android.target.classpath">
+                <pathconvert property="project.target.classpath.value" refid="project.target.class.path">
                     <firstmatchmapper>
                         <regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/>
                         <identitymapper/>
@@ -780,15 +829,15 @@
                 <!-- Build a path object with all the jar files that must be obfuscated.
                      This include the project compiled source code and any 3rd party jar
                      files. -->
-                <path id="project.jars.ref">
+                <path id="project.all.classes.path">
                     <pathelement location="${preobfuscate.jar.file}" />
-                    <path refid="project.libraries.jars" />
+                    <path refid="project.all.jars.path" />
                 </path>
                 <!-- Set the project jar files Path object into a single property. It'll be
                      all the jar files separated by a platform path-separator.
                      Each path must be quoted if it contains spaces.
                 -->
-                <pathconvert property="project.jars" refid="project.jars.ref">
+                <pathconvert property="project.all.classes.value" refid="project.all.classes.path">
                     <firstmatchmapper>
                         <regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/>
                         <identitymapper/>
@@ -813,9 +862,9 @@
                     destfile="${preobfuscate.jar.file}" />
                 <proguard>
                     -include      "${proguard.configcmd}"
-                    -injars       ${project.jars}
+                    -injars       ${project.all.classes.value}
                     -outjars      "${obfuscated.jar.file}"
-                    -libraryjars  ${android.libraryjars}
+                    -libraryjars  ${project.target.classpath.value}
                     -dump         "${obfuscate.absolute.dir}/dump.txt"
                     -printseeds   "${obfuscate.absolute.dir}/seeds.txt"
                     -printusage   "${obfuscate.absolute.dir}/usage.txt"
@@ -875,13 +924,13 @@
                     debug="${build.is.packaging.debug}"
                     manifest="AndroidManifest.xml"
                     assets="${asset.absolute.dir}"
-                    androidjar="${android.jar}"
+                    androidjar="${project.target.android.jar}"
                     apkfolder="${out.absolute.dir}"
                     nocrunch="${build.packaging.nocrunch}"
                     resourcefilename="${resource.package.file.name}"
                     resourcefilter="${aapt.resource.filter}"
-                    projectLibrariesResName="project.libraries.res"
-                    projectLibrariesPackageName="project.libraries.package"
+                    libraryResFolderPathRefid="project.library.res.folder.path"
+                    libraryPackagesRefid="project.library.packages"
                     previousBuildType="${build.last.target}"
                     buildType="${build.target}">
                 <res path="${out.res.absolute.dir}" />
@@ -932,11 +981,24 @@
     </target>
 
 
-    <target name="-set-debug-mode">
+    <target name="-set-debug-mode" depends="-setup">
         <!-- record the current build target -->
         <property name="build.target" value="debug" />
 
-        <property name="build.is.instrumented" value="false" />
+        <if>
+            <condition>
+                <and>
+                    <istrue value="${project.is.testapp}" />
+                    <istrue value="${emma.enabled}" />
+                </and>
+            </condition>
+            <then>
+                <property name="build.is.instrumented" value="true" />
+            </then>
+            <else>
+                <property name="build.is.instrumented" value="false" />
+            </else>
+        </if>
 
         <!-- whether the build is a debug build. always set. -->
         <property name="build.is.packaging.debug" value="true" />
@@ -1131,33 +1193,40 @@
     </target>
 
     <!-- fails if the project is not a test project -->
-    <target name="-test-project-check">
-        <!-- can't use project.is.test since the setup target is not run -->
+    <target name="-test-project-check" depends="-setup">
         <if>
             <condition>
-                <isset property="tested.project.dir" />
+                <and>
+                    <isfalse value="${project.is.test}" />
+                    <isfalse value="${project.is.testapp}" />
+                </and>
             </condition>
-            <else>
+            <then>
                 <fail message="Project is not a test project." />
-            </else>
+            </then>
         </if>
     </target>
 
     <target name="test" depends="-test-project-check"
                 description="Runs tests from the package defined in test.package property">
-
-        <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
-
         <property name="test.runner" value="android.test.InstrumentationTestRunner" />
 
-        <!-- Application package of the tested project extracted from its manifest file -->
-        <xpath input="${tested.project.absolute.dir}/AndroidManifest.xml"
-                expression="/manifest/@package" output="tested.manifest.package" />
-        <xpath input="AndroidManifest.xml"
-                expression="/manifest/@package" output="manifest.package" />
+        <if condition="${project.is.test}">
+        <then>
+            <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
+
+            <!-- Application package of the tested project extracted from its manifest file -->
+            <xpath input="${tested.project.absolute.dir}/AndroidManifest.xml"
+                    expression="/manifest/@package" output="tested.project.app.package" />
+        </then>
+        <else>
+            <!-- this is a test app, the tested package is the app's own package -->
+            <property name="tested.project.app.package" value="${project.app.package}" />
+        </else>
+        </if>
 
         <property name="emma.dump.file"
-                value="/data/data/${tested.manifest.package}/coverage.ec" />
+                value="/data/data/${tested.project.app.package}/coverage.ec" />
 
         <if condition="${emma.enabled}">
             <then>
@@ -1294,18 +1363,14 @@
 
 
     <!-- Uninstalls the package from the default emulator/device -->
-    <target name="uninstall"
+    <target name="uninstall" depends="-setup"
                 description="Uninstalls the application from a running emulator or device.">
-        <!-- Name of the application package extracted from manifest file -->
-        <xpath input="AndroidManifest.xml" expression="/manifest/@package"
-                output="manifest.package" />
-
         <if>
             <condition>
-                <isset property="manifest.package" />
+                <isset property="project.app.package" />
             </condition>
             <then>
-                <uninstall-helper app.package="${manifest.package}" />
+                <uninstall-helper app.package="${project.app.package}" />
             </then>
             <else>
                 <fail message="Could not find application package in manifest. Cannot run 'adb uninstall'." />
@@ -1313,11 +1378,10 @@
         </if>
 
         <!-- Now uninstall the tested project, if applicable -->
-        <!-- can't use project.is.test since the setup target might not have run -->
         <if>
             <condition>
                 <and>
-                    <isset property="tested.project.dir" />
+                    <istrue value="${project.is.test}" />
                     <not>
                         <isset property="dont.do.deps" />
                     </not>
@@ -1328,13 +1392,13 @@
 
                 <!-- Application package of the tested project extracted from its manifest file -->
                 <xpath input="${tested.project.absolute.dir}/AndroidManifest.xml"
-                    expression="/manifest/@package" output="tested.manifest.package" />
+                    expression="/manifest/@package" output="tested.project.app.package" />
                 <if>
                     <condition>
-                        <isset property="tested.manifest.package" />
+                        <isset property="tested.project.app.package" />
                     </condition>
                     <then>
-                        <uninstall-helper app.package="${tested.manifest.package}" />
+                        <uninstall-helper app.package="${tested.project.app.package}" />
                     </then>
                     <else>
                         <fail message="Could not find tested application package in manifest. Cannot run 'adb uninstall'." />
@@ -1372,7 +1436,7 @@
         <echo>              debug key.</echo>
         <echo>   test:      Runs the tests. Project must be a test project and</echo>
         <echo>              must have been built. Typical usage would be:</echo>
-        <echo>                  ant [emma] debug installt test</echo>
+        <echo>                  ant [emma] debug install test</echo>
         <echo>   emma:      Transiently enables code coverage for subsequent</echo>
         <echo>              targets.</echo>
         <echo>   install:   Installs the newly build package. Must either be used</echo>
diff --git a/files/ant/pre_setup.xml b/files/ant/pre_setup.xml
deleted file mode 100644
index 1c86109..0000000
--- a/files/ant/pre_setup.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="imported" basedir=".">
-
-    <fail message="Your build.xml file is outdated. Delete it and regenerate it with 'android update project'"/>
-
-</project>
diff --git a/files/tools_source.properties b/files/tools_source.properties
index a4b2625..515ff6b 100644
--- a/files/tools_source.properties
+++ b/files/tools_source.properties
@@ -1,3 +1,3 @@
 Pkg.UserSrc=false
-Pkg.Revision=19
+Pkg.Revision=20
 Platform.MinPlatformToolsRev=11
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/IPropertySource.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/IPropertySource.java
new file mode 100644
index 0000000..360c755
--- /dev/null
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/IPropertySource.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sdklib.internal.project;
+
+/**
+ * A source able to return properties by name.
+ *
+ */
+public interface IPropertySource {
+    String getProperty(String name);
+}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
index 33f56ce..09a35c5 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
@@ -54,7 +54,7 @@
  * {@link #makeWorkingCopy()}.
  *
  */
-public class ProjectProperties {
+public class ProjectProperties implements IPropertySource {
     protected final static Pattern PATTERN_PROP = Pattern.compile(
     "^([a-zA-Z0-9._-]+)\\s*=\\s*(.*)\\s*$");
 
@@ -344,6 +344,7 @@
      * @param name the name of the property.
      * @return the property value or null if the property is not set.
      */
+    @Override
     public synchronized String getProperty(String name) {
         return mProperties.get(name);
     }
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectPropertiesWorkingCopy.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectPropertiesWorkingCopy.java
index 13c8f6a..797b505 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectPropertiesWorkingCopy.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectPropertiesWorkingCopy.java
@@ -90,18 +90,15 @@
      * <p/>
      * Typical usage:
      * <ul>
-     * <li>Create a ProjectProperties with {@code PropertyType#BUILD}
-     * <li>Merge in values using {@code PropertyType#DEFAULT}
+     * <li>Create a ProjectProperties with {@code PropertyType#ANT}
+     * <li>Merge in values using {@code PropertyType#PROJECT}
      * <li>The result is that this contains all the properties from default plus those
      *     overridden by the build.properties file.
      * </ul>
      *
      * @param type One the possible {@link PropertyType}s.
      * @return this object, for chaining.
-     *
-     * @deprecated FIXME this method is not referenced anywhere.
      */
-    @Deprecated
     public synchronized ProjectPropertiesWorkingCopy merge(PropertyType type) {
         if (mProjectFolder.exists() && mType != type) {
             IAbstractFile propFile = mProjectFolder.getFile(type.getFilename());
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidXPathFactory.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidXPathFactory.java
index 8373d8a..d6b2a6b 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidXPathFactory.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/xml/AndroidXPathFactory.java
@@ -18,7 +18,7 @@
 
 import com.android.sdklib.SdkConstants;
 
-import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
@@ -42,7 +42,7 @@
                 DEFAULT_NS_PREFIX);
 
         private final String mAndroidPrefix;
-        private final List<String> mAndroidPrefixes = new ArrayList<String>();
+        private final List<String> mAndroidPrefixes;
 
         /**
          * Returns the default {@link AndroidNamespaceContext}.
@@ -57,7 +57,7 @@
          */
         public AndroidNamespaceContext(String androidPrefix) {
             mAndroidPrefix = androidPrefix;
-            mAndroidPrefixes.add(mAndroidPrefix);
+            mAndroidPrefixes = Collections.singletonList(mAndroidPrefix);
         }
 
         @Override
diff --git a/templates/build.template b/templates/build.template
index 3c0ffc8..1ab7ea2 100644
--- a/templates/build.template
+++ b/templates/build.template
@@ -39,9 +39,16 @@
          application and should be checked into Version Control Systems. -->
     <loadproperties srcFile="project.properties" />
 
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var. -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
     <!-- quick check on sdk.dir -->
     <fail
-            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through an env var"
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
             unless="sdk.dir"
     />
 
diff --git a/testapps/.gitignore b/testapps/.gitignore
index 74f2472..3d82821 100644
--- a/testapps/.gitignore
+++ b/testapps/.gitignore
@@ -1,4 +1,5 @@
 bin
+coverage
 local.properties
 gen
 proguard
diff --git a/testapps/customViewTest/libWithCustomView/local.properties b/testapps/customViewTest/libWithCustomView/local.properties
deleted file mode 100644
index 613788a..0000000
--- a/testapps/customViewTest/libWithCustomView/local.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must *NOT* be checked in Version Control Systems,
-# as it contains information specific to your local configuration.
-
-# location of the SDK. This is only used by Ant
-# For customization when using a Version Control System, please read the
-# header note.
-sdk.dir=/android-sdk-dev
diff --git a/testapps/customViewTest/mainProject/local.properties b/testapps/customViewTest/mainProject/local.properties
deleted file mode 100644
index 613788a..0000000
--- a/testapps/customViewTest/mainProject/local.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must *NOT* be checked in Version Control Systems,
-# as it contains information specific to your local configuration.
-
-# location of the SDK. This is only used by Ant
-# For customization when using a Version Control System, please read the
-# header note.
-sdk.dir=/android-sdk-dev
diff --git a/testapps/libsAndJarTest/lib1/src/com/android/tests/javaprojecttest/lib1/Main.java b/testapps/libsAndJarTest/lib1/src/com/android/tests/javaprojecttest/lib1/Main.java
index f09e1cd..1c3ed35 100644
--- a/testapps/libsAndJarTest/lib1/src/com/android/tests/javaprojecttest/lib1/Main.java
+++ b/testapps/libsAndJarTest/lib1/src/com/android/tests/javaprojecttest/lib1/Main.java
@@ -3,6 +3,8 @@
 import android.app.Activity;
 import android.os.Bundle;
 
+import com.android.tests.javaprojecttest.lib2.Lib2;
+
 public class Main extends Activity
 {
     /** Called when the activity is first created. */
@@ -11,5 +13,8 @@
     {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
+
+        //Access some class from Lib2 to make sure we can access them.
+        String foo = Lib2.getContent();
     }
 }
diff --git a/testapps/testProjectTest/app/build.xml b/testapps/testProjectTest/app/build.xml
new file mode 100644
index 0000000..a6975a4
--- /dev/null
+++ b/testapps/testProjectTest/app/build.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="LibActivity" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var. -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/testapps/testProjectTest/app/src/readme.txt b/testapps/testProjectTest/app/src/readme.txt
new file mode 100644
index 0000000..103fd76
--- /dev/null
+++ b/testapps/testProjectTest/app/src/readme.txt
@@ -0,0 +1 @@
+Just there so that the src folder doesn't disappear.
\ No newline at end of file
diff --git a/testapps/testProjectTest/lib/build.xml b/testapps/testProjectTest/lib/build.xml
new file mode 100644
index 0000000..aaf0ab1
--- /dev/null
+++ b/testapps/testProjectTest/lib/build.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="lib" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var. -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/testapps/testProjectTest/test/res/drawable-hdpi/ic_launcher.png b/testapps/testProjectTest/test/res/drawable-hdpi/ic_launcher.png
deleted file mode 100644
index 96a442e..0000000
--- a/testapps/testProjectTest/test/res/drawable-hdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/testapps/testProjectTest/test/res/drawable-ldpi/ic_launcher.png b/testapps/testProjectTest/test/res/drawable-ldpi/ic_launcher.png
deleted file mode 100644
index 9923872..0000000
--- a/testapps/testProjectTest/test/res/drawable-ldpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/testapps/testProjectTest/test/res/drawable-mdpi/ic_launcher.png b/testapps/testProjectTest/test/res/drawable-mdpi/ic_launcher.png
deleted file mode 100644
index 359047d..0000000
--- a/testapps/testProjectTest/test/res/drawable-mdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/testapps/testProjectTest/test/res/drawable-xhdpi/ic_launcher.png b/testapps/testProjectTest/test/res/drawable-xhdpi/ic_launcher.png
deleted file mode 100644
index 71c6d76..0000000
--- a/testapps/testProjectTest/test/res/drawable-xhdpi/ic_launcher.png
+++ /dev/null
Binary files differ
diff --git a/testapps/testProjectTest/test/res/layout/main.xml b/testapps/testProjectTest/test/res/layout/main.xml
deleted file mode 100644
index bc12cd8..0000000
--- a/testapps/testProjectTest/test/res/layout/main.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:orientation="vertical" >
-
-    <TextView
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:text="@string/hello" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/testapps/testProjectTest/test/.classpath b/testapps/testProjectTest/testapp/.classpath
similarity index 100%
rename from testapps/testProjectTest/test/.classpath
rename to testapps/testProjectTest/testapp/.classpath
diff --git a/testapps/testProjectTest/test/.project b/testapps/testProjectTest/testapp/.project
similarity index 95%
copy from testapps/testProjectTest/test/.project
copy to testapps/testProjectTest/testapp/.project
index bffbba0..796ccc1 100644
--- a/testapps/testProjectTest/test/.project
+++ b/testapps/testProjectTest/testapp/.project
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>testProjectTest-test</name>
+	<name>testProjectTest-testapp</name>
 	<comment></comment>
 	<projects>
 		<project>testProjectTest-app</project>
diff --git a/testapps/testProjectTest/test/AndroidManifest.xml b/testapps/testProjectTest/testapp/AndroidManifest.xml
similarity index 94%
rename from testapps/testProjectTest/test/AndroidManifest.xml
rename to testapps/testProjectTest/testapp/AndroidManifest.xml
index 8ac5dbe..5252972 100644
--- a/testapps/testProjectTest/test/AndroidManifest.xml
+++ b/testapps/testProjectTest/testapp/AndroidManifest.xml
@@ -11,7 +11,7 @@
          this package needs to link against the android.test library,
          which is needed when building test cases.
     -->
-    <application>
+    <application android:label="testProjectTest-testapp">
         <uses-library android:name="android.test.runner" />
     </application>
 
diff --git a/testapps/testProjectTest/testapp/build.xml b/testapps/testProjectTest/testapp/build.xml
new file mode 100644
index 0000000..2682e1c
--- /dev/null
+++ b/testapps/testProjectTest/testapp/build.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="testapp" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var. -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/testapps/testProjectTest/test/proguard-project.txt b/testapps/testProjectTest/testapp/proguard-project.txt
similarity index 100%
rename from testapps/testProjectTest/test/proguard-project.txt
rename to testapps/testProjectTest/testapp/proguard-project.txt
diff --git a/testapps/testProjectTest/test/project.properties b/testapps/testProjectTest/testapp/project.properties
similarity index 100%
rename from testapps/testProjectTest/test/project.properties
rename to testapps/testProjectTest/testapp/project.properties
diff --git a/testapps/testProjectTest/test/src/com/android/tests/testprojecttest/lib/LibActivityTest.java b/testapps/testProjectTest/testapp/src/com/android/tests/testprojecttest/lib/LibActivityTest.java
similarity index 100%
rename from testapps/testProjectTest/test/src/com/android/tests/testprojecttest/lib/LibActivityTest.java
rename to testapps/testProjectTest/testapp/src/com/android/tests/testprojecttest/lib/LibActivityTest.java
diff --git a/testapps/testProjectTest/test/src/com/android/tests/testprojecttest/test/AllTests.java b/testapps/testProjectTest/testapp/src/com/android/tests/testprojecttest/test/AllTests.java
similarity index 100%
rename from testapps/testProjectTest/test/src/com/android/tests/testprojecttest/test/AllTests.java
rename to testapps/testProjectTest/testapp/src/com/android/tests/testprojecttest/test/AllTests.java
diff --git a/testapps/testProjectTest/test/.classpath b/testapps/testProjectTest/testlib/.classpath
similarity index 100%
copy from testapps/testProjectTest/test/.classpath
copy to testapps/testProjectTest/testlib/.classpath
diff --git a/testapps/testProjectTest/test/.project b/testapps/testProjectTest/testlib/.project
similarity index 95%
rename from testapps/testProjectTest/test/.project
rename to testapps/testProjectTest/testlib/.project
index bffbba0..8450217 100644
--- a/testapps/testProjectTest/test/.project
+++ b/testapps/testProjectTest/testlib/.project
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
-	<name>testProjectTest-test</name>
+	<name>testProjectTest-testlib</name>
 	<comment></comment>
 	<projects>
 		<project>testProjectTest-app</project>
diff --git a/testapps/testProjectTest/testlib/AndroidManifest.xml b/testapps/testProjectTest/testlib/AndroidManifest.xml
new file mode 100644
index 0000000..acfe650
--- /dev/null
+++ b/testapps/testProjectTest/testlib/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.tests.testprojecttest.testlib"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk android:minSdkVersion="15" />
+
+    <!--
+         We add an application tag here just so that we can indicate that
+         this package needs to link against the android.test library,
+         which is needed when building test cases.
+    -->
+    <application android:label="testProjectTest-testlib">
+        <uses-library android:name="android.test.runner" />
+
+        <activity
+            android:name="com.android.tests.testprojecttest.lib.LibActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+
+    <!--
+    This declares that this app uses the instrumentation test runner targeting
+    the package of com.android.tests.testprojecttest.testlib.  To run the tests use the command:
+    "adb shell am instrument -w com.android.tests.testprojecttest.testlib/android.test.InstrumentationTestRunner"
+    -->
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.tests.testprojecttest.testlib" />
+
+</manifest>
\ No newline at end of file
diff --git a/testapps/testProjectTest/testlib/build.xml b/testapps/testProjectTest/testlib/build.xml
new file mode 100644
index 0000000..7771647
--- /dev/null
+++ b/testapps/testProjectTest/testlib/build.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="testlib" default="help">
+
+    <!-- The local.properties file is created and updated by the 'android' tool.
+         It contains the path to the SDK. It should *NOT* be checked into
+         Version Control Systems. -->
+    <property file="local.properties" />
+
+    <!-- The ant.properties file can be created by you. It is only edited by the
+         'android' tool to add properties to it.
+         This is the place to change some Ant specific build properties.
+         Here are some properties you may want to change/update:
+
+         source.dir
+             The name of the source directory. Default is 'src'.
+         out.dir
+             The name of the output directory. Default is 'bin'.
+
+         For other overridable properties, look at the beginning of the rules
+         files in the SDK, at tools/ant/build.xml
+
+         Properties related to the SDK location or the project target should
+         be updated using the 'android' tool with the 'update' action.
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems.
+
+         -->
+    <property file="ant.properties" />
+
+    <!-- The project.properties file is created and updated by the 'android'
+         tool, as well as ADT.
+
+         This contains project specific properties such as project target, and library
+         dependencies. Lower level build properties are stored in ant.properties
+         (or in .classpath for Eclipse projects).
+
+         This file is an integral part of the build system for your
+         application and should be checked into Version Control Systems. -->
+    <loadproperties srcFile="project.properties" />
+
+    <!-- if sdk.dir was not set from one of the property file, then
+         get it from the ANDROID_HOME env var. -->
+    <property environment="env" />
+    <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+        <isset property="env.ANDROID_HOME" />
+    </condition>
+
+    <!-- quick check on sdk.dir -->
+    <fail
+            message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+            unless="sdk.dir"
+    />
+
+    <!--
+        Import per project custom build rules if present at the root of the project.
+        This is the place to put custom intermediary targets such as:
+            -pre-build
+            -pre-compile
+            -post-compile (This is typically used for code obfuscation.
+                           Compiled code location: ${out.classes.absolute.dir}
+                           If this is not done in place, override ${out.dex.input.absolute.dir})
+            -post-package
+            -post-build
+            -pre-clean
+    -->
+    <import file="custom_rules.xml" optional="true" />
+
+    <!-- Import the actual build file.
+
+         To customize existing targets, there are two options:
+         - Customize only one target:
+             - copy/paste the target into this file, *before* the
+               <import> task.
+             - customize it to your needs.
+         - Customize the whole content of build.xml
+             - copy/paste the content of the rules files (minus the top node)
+               into this file, replacing the <import> task.
+             - customize to your needs.
+
+         ***********************
+         ****** IMPORTANT ******
+         ***********************
+         In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+         in order to avoid having your file be overridden by tools such as "android update project"
+    -->
+    <!-- version-tag: 1 -->
+    <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/testapps/testProjectTest/test/proguard-project.txt b/testapps/testProjectTest/testlib/proguard-project.txt
similarity index 100%
copy from testapps/testProjectTest/test/proguard-project.txt
copy to testapps/testProjectTest/testlib/proguard-project.txt
diff --git a/testapps/testProjectTest/testlib/project.properties b/testapps/testProjectTest/testlib/project.properties
new file mode 100644
index 0000000..60765b6
--- /dev/null
+++ b/testapps/testProjectTest/testlib/project.properties
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-15
+android.library.reference.1=../lib
diff --git a/testapps/testProjectTest/test/res/values/strings.xml b/testapps/testProjectTest/testlib/res/values/strings.xml
similarity index 100%
rename from testapps/testProjectTest/test/res/values/strings.xml
rename to testapps/testProjectTest/testlib/res/values/strings.xml
diff --git a/testapps/testProjectTest/testlib/src/com/android/tests/testprojecttest/lib/LibActivityTest.java b/testapps/testProjectTest/testlib/src/com/android/tests/testprojecttest/lib/LibActivityTest.java
new file mode 100644
index 0000000..6632c58
--- /dev/null
+++ b/testapps/testProjectTest/testlib/src/com/android/tests/testprojecttest/lib/LibActivityTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008 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.tests.testprojecttest.lib;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.widget.TextView;
+
+import com.android.tests.testprojecttest.lib.R;
+
+/**
+ * An example of an {@link ActivityInstrumentationTestCase2} of a specific activity {@link Focus2}.
+ * By virtue of extending {@link ActivityInstrumentationTestCase2}, the target activity is automatically
+ * launched and finished before and after each test.  This also extends
+ * {@link android.test.InstrumentationTestCase}, which provides
+ * access to methods for sending events to the target activity, such as key and
+ * touch events.  See {@link #sendKeys}.
+ *
+ * In general, {@link android.test.InstrumentationTestCase}s and {@link ActivityInstrumentationTestCase2}s
+ * are heavier weight functional tests available for end to end testing of your
+ * user interface.  When run via a {@link android.test.InstrumentationTestRunner},
+ * the necessary {@link android.app.Instrumentation} will be injected for you to
+ * user via {@link #getInstrumentation} in your tests.
+ *
+ * See {@link com.example.android.apis.AllTests} for documentation on running
+ * all tests and individual tests in this application.
+ */
+public class LibActivityTest extends ActivityInstrumentationTestCase2<LibActivity> {
+
+    private TextView mTextView;
+
+    /**
+     * Creates an {@link ActivityInstrumentationTestCase2} that tests the {@link Focus2} activity.
+     */
+    public LibActivityTest() {
+        super(LibActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        final LibActivity a = getActivity();
+        // ensure a valid handle to the activity has been returned
+        assertNotNull(a);
+        mTextView = (TextView) a.findViewById(R.id.text);
+    }
+
+    /**
+     * The name 'test preconditions' is a convention to signal that if this
+     * test doesn't pass, the test case was not set up properly and it might
+     * explain any and all failures in other tests.  This is not guaranteed
+     * to run before other tests, as junit uses reflection to find the tests.
+     */
+    @MediumTest
+    public void testPreconditions() {
+        assertNotNull(mTextView);
+    }
+}
diff --git a/testapps/testProjectTest/test/src/com/android/tests/testprojecttest/test/AllTests.java b/testapps/testProjectTest/testlib/src/com/android/tests/testprojecttest/test/AllTests.java
similarity index 100%
copy from testapps/testProjectTest/test/src/com/android/tests/testprojecttest/test/AllTests.java
copy to testapps/testProjectTest/testlib/src/com/android/tests/testprojecttest/test/AllTests.java