auto import from //branches/cupcake/...@137197
diff --git a/apps/Development/Android.mk b/apps/Development/Android.mk
index 9578e79..a666d7f 100644
--- a/apps/Development/Android.mk
+++ b/apps/Development/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := eng development tests
+LOCAL_MODULE_TAGS := eng
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_STATIC_JAVA_LIBRARIES := googlelogin-client
diff --git a/apps/Fallback/Android.mk b/apps/Fallback/Android.mk
index 64b7d17..0a7f5cf 100644
--- a/apps/Fallback/Android.mk
+++ b/apps/Fallback/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := user development
+LOCAL_MODULE_TAGS := user
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
diff --git a/apps/SdkSetup/Android.mk b/apps/SdkSetup/Android.mk
index 538c2cb..7647f15 100644
--- a/apps/SdkSetup/Android.mk
+++ b/apps/SdkSetup/Android.mk
@@ -1,8 +1,6 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := user
-
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
 LOCAL_PACKAGE_NAME := SdkSetup
diff --git a/apps/SpareParts/Android.mk b/apps/SpareParts/Android.mk
index ccf6c6d..1a1ea0a 100644
--- a/apps/SpareParts/Android.mk
+++ b/apps/SpareParts/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := eng development
+LOCAL_MODULE_TAGS := eng
 
 LOCAL_SRC_FILES := $(call all-subdir-java-files)
 
diff --git a/apps/SpareParts/res/values/strings.xml b/apps/SpareParts/res/values/strings.xml
index 21c2df9..6aecca8 100644
--- a/apps/SpareParts/res/values/strings.xml
+++ b/apps/SpareParts/res/values/strings.xml
@@ -57,10 +57,6 @@
     <string name="summary_end_button">Select End (red) button action</string>
     <string name="dialog_title_end_button">Select End button</string>
     
-    <string name="title_accelerometer">Display rotation</string>
-    <string name="summary_on_accelerometer">Display rotates from orientation</string>
-    <string name="summary_off_accelerometer">Display rotates from orientation</string>
-    
     <string name="applications_title">Applications</string>
     
     <string name="title_maps_compass">Show compass in Maps</string>
diff --git a/apps/SpareParts/res/xml/spare_parts.xml b/apps/SpareParts/res/xml/spare_parts.xml
index 5141e22..3e06397 100644
--- a/apps/SpareParts/res/xml/spare_parts.xml
+++ b/apps/SpareParts/res/xml/spare_parts.xml
@@ -89,12 +89,6 @@
                 android:dialogTitle="@string/dialog_title_end_button" />
         
         <CheckBoxPreference 
-            android:key="accelerometer" 
-            android:title="@string/title_accelerometer" 
-            android:summaryOn="@string/summary_on_accelerometer"
-            android:summaryOff="@string/summary_off_accelerometer"/>
-        
-        <CheckBoxPreference 
             android:key="haptic_feedback" 
             android:title="@string/title_haptic_feedback" 
             android:summaryOn="@string/summary_on_haptic_feedback"
diff --git a/apps/SpareParts/src/com/android/spare_parts/SpareParts.java b/apps/SpareParts/src/com/android/spare_parts/SpareParts.java
index 4852ec2..2507746 100644
--- a/apps/SpareParts/src/com/android/spare_parts/SpareParts.java
+++ b/apps/SpareParts/src/com/android/spare_parts/SpareParts.java
@@ -57,7 +57,6 @@
     private static final String HAPTIC_FEEDBACK_PREF = "haptic_feedback";
     private static final String FONT_SIZE_PREF = "font_size";
     private static final String END_BUTTON_PREF = "end_button";
-    private static final String ACCELEROMETER_PREF = "accelerometer";
     private static final String MAPS_COMPASS_PREF = "maps_compass";
     
     private final Configuration mCurConfig = new Configuration();
@@ -68,7 +67,6 @@
     private CheckBoxPreference mHapticFeedbackPref;
     private ListPreference mFontSizePref;
     private ListPreference mEndButtonPref;
-    private CheckBoxPreference mAccelerometerPref;
     private CheckBoxPreference mShowMapsCompassPref;
     
     private IWindowManager mWindowManager;
@@ -125,7 +123,6 @@
         mFontSizePref.setOnPreferenceChangeListener(this);
         mEndButtonPref = (ListPreference) prefSet.findPreference(END_BUTTON_PREF);
         mEndButtonPref.setOnPreferenceChangeListener(this);
-        mAccelerometerPref = (CheckBoxPreference) prefSet.findPreference(ACCELEROMETER_PREF);
         mShowMapsCompassPref = (CheckBoxPreference) prefSet.findPreference(MAPS_COMPASS_PREF);
         
         mWindowManager = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
@@ -149,9 +146,6 @@
             mHapticFeedbackPref.setChecked(Settings.System.getInt(
                     getContentResolver(), 
                     Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) != 0);
-            mAccelerometerPref.setChecked(Settings.System.getInt(
-                    getContentResolver(), 
-                    Settings.System.ACCELEROMETER_ROTATION, 0) != 0);
             Context c = createPackageContext("com.google.android.apps.maps", 0);
             mShowMapsCompassPref.setChecked(c.getSharedPreferences("extra-features", MODE_WORLD_READABLE)
                 .getBoolean("compass", false));
@@ -243,11 +237,7 @@
     }
     
     public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
-        if (ACCELEROMETER_PREF.equals(key)) {
-            Settings.System.putInt(getContentResolver(),
-                    Settings.System.ACCELEROMETER_ROTATION,
-                    mAccelerometerPref.isChecked() ? 1 : 0);
-        } else if (FANCY_IME_ANIMATIONS_PREF.equals(key)) {
+        if (FANCY_IME_ANIMATIONS_PREF.equals(key)) {
             Settings.System.putInt(getContentResolver(),
                     Settings.System.FANCY_IME_ANIMATIONS,
                     mFancyImeAnimationsPref.isChecked() ? 1 : 0);
diff --git a/samples/ApiDemos/Android.mk b/samples/ApiDemos/Android.mk
index 5019c2f..e10ef43 100644
--- a/samples/ApiDemos/Android.mk
+++ b/samples/ApiDemos/Android.mk
@@ -1,7 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_MODULE_TAGS := samples development
+LOCAL_MODULE_TAGS := samples
 
 # Only compile source java files in this apk.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
index a870e23..9aeb2b5 100644
--- a/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
+++ b/samples/SoftKeyboard/src/com/example/android/softkeyboard/SoftKeyboard.java
@@ -253,6 +253,8 @@
     @Override public void onUpdateSelection(int oldSelStart, int oldSelEnd,
             int newSelStart, int newSelEnd,
             int candidatesStart, int candidatesEnd) {
+        super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
+                candidatesStart, candidatesEnd);
         
         // If the current selection in the text view changes, we should
         // clear whatever candidate text we have.
diff --git a/simulator/app/PropertyServer.cpp b/simulator/app/PropertyServer.cpp
index 0d6054f..4b1aedd 100644
--- a/simulator/app/PropertyServer.cpp
+++ b/simulator/app/PropertyServer.cpp
@@ -108,6 +108,8 @@
         { "ro.SECONDARY_SERVER_MEM", "4096" },
         { "ro.HIDDEN_APP_MEM", "8192" },
         { "ro.EMPTY_APP_MEM", "16384" },
+        { "ro.HOME_APP_ADJ", "4" },
+        { "ro.HOME_APP_MEM", "4096" },
         //{ "init.svc.adbd", "running" },       // causes ADB-JDWP
         { "init.svc.usbd", "running" },
         { "init.svc.debuggerd", "running" },
diff --git a/tools/draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java b/tools/draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java
index 6901c98..84b96a5 100644
--- a/tools/draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java
+++ b/tools/draw9patch/src/com/android/draw9patch/ui/ImageEditorPanel.java
@@ -478,6 +478,14 @@
                         start = rect.x;
                     }
                 }
+            } else {
+                int start = -1;
+                for (Rectangle rect : patches) {
+                    if (rect.x > start) {
+                        horizontalPatchesSum += rect.width;
+                        start = rect.x;
+                    }
+                }
             }
 
             verticalPatchesSum = 0;
@@ -489,6 +497,14 @@
                         start = rect.y;
                     }
                 }
+            } else {
+                int start = -1;
+                for (Rectangle rect : patches) {
+                    if (rect.y > start) {
+                        verticalPatchesSum += rect.height;
+                        start = rect.y;
+                    }
+                }
             }
 
             setSize(size);
@@ -528,8 +544,7 @@
                 x = 0;
                 y = 0;
 
-                if (patches.size() == 0 || horizontalPatches.size() == 0 ||
-                        verticalPatches.size() == 0) {
+                if (patches.size() == 0) {
                     g.drawImage(image, 0, 0, scaledWidth, scaledHeight, null);
                     g2.dispose();
                     return;
@@ -1028,7 +1043,15 @@
                 horizontalPatches = getRectangles(left.first, top.second);
                 verticalPatches = getRectangles(left.second, top.first);
             } else {
-                horizontalPatches = verticalPatches = new ArrayList<Rectangle>(0);
+                if (top.first.size() > 0) {
+                    horizontalPatches = new ArrayList<Rectangle>(0);
+                    verticalPatches = getVerticalRectangles(top.first);
+                } else if (left.first.size() > 0) {
+                    horizontalPatches = getHorizontalRectangles(left.first);
+                    verticalPatches = new ArrayList<Rectangle>(0);
+                } else {
+                    horizontalPatches = verticalPatches = new ArrayList<Rectangle>(0);
+                }
             }
 
             row = GraphicsUtilities.getPixels(image, 0, height - 1, width, 1, row);
@@ -1041,6 +1064,28 @@
             verticalPadding = getPadding(left.first);
         }
 
+        private List<Rectangle> getVerticalRectangles(List<Pair<Integer>> topPairs) {
+            List<Rectangle> rectangles = new ArrayList<Rectangle>();
+            for (Pair<Integer> top : topPairs) {
+                int x = top.first;
+                int width = top.second - top.first;
+
+                rectangles.add(new Rectangle(x, 1, width, image.getHeight() - 2));
+            }
+            return rectangles;
+        }
+
+        private List<Rectangle> getHorizontalRectangles(List<Pair<Integer>> leftPairs) {
+            List<Rectangle> rectangles = new ArrayList<Rectangle>();
+            for (Pair<Integer> left : leftPairs) {
+                int y = left.first;
+                int height = left.second - left.first;
+
+                rectangles.add(new Rectangle(1, y, image.getWidth() - 2, height));
+            }
+            return rectangles;
+        }
+
         private Pair<Integer> getPadding(List<Pair<Integer>> pairs) {
             if (pairs.size() == 0) {
                 return new Pair<Integer>(0, 0);
@@ -1063,7 +1108,7 @@
             for (Pair<Integer> left : leftPairs) {
                 int y = left.first;
                 int height = left.second - left.first;
-                for (Pair<Integer> top: topPairs) {
+                for (Pair<Integer> top : topPairs) {
                     int x = top.first;
                     int width = top.second - top.first;
 
@@ -1108,6 +1153,7 @@
                 startWithPatch[0] = true;
                 fixed.clear();
             }
+
             return new Pair<List<Pair<Integer>>>(fixed, patches);
         }
 
diff --git a/tools/draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java b/tools/draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java
index a62884f..f14cd77 100644
--- a/tools/draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java
+++ b/tools/draw9patch/src/com/android/draw9patch/ui/ImageTransferHandler.java
@@ -36,25 +36,48 @@
     @Override
     public boolean importData(JComponent component, Transferable transferable) {
         try {
-            Object data = transferable.getTransferData(DataFlavor.javaFileListFlavor);
-            //noinspection unchecked
-            final File file = ((List<File>) data).get(0);
-            mainFrame.open(file).execute();
+            for (DataFlavor flavor : transferable.getTransferDataFlavors()) {
+                if (flavor.isFlavorJavaFileListType()) {
+                    Object data = transferable.getTransferData(DataFlavor.javaFileListFlavor);
+                    //noinspection unchecked
+                    final File file = ((List<File>) data).get(0);
+                    mainFrame.open(file).execute();
+                    return true;
+                } else if (flavor.isFlavorTextType()) {
+                    if (flavor.getRepresentationClass() == String.class) {
+                        String mime = flavor.getMimeType();
+                        DataFlavor flave = new DataFlavor(mime);
+                        Object data = transferable.getTransferData(flave);
+                        final String path = convertPath(data.toString());
+                        mainFrame.open(new File(path)).execute();
+                        return true;
+                    }
+                }
+            }
         } catch (UnsupportedFlavorException e) {
-            return false;
+            // Ignore
         } catch (MalformedURLException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
         }
 
-        return true;
+        return false;
+    }
+
+    private static String convertPath(String path) {
+        if (path.startsWith("file://")) path = path.substring("file://".length());
+        if (path.indexOf('\n') != -1) path = path.substring(0, path.indexOf('\n'));
+        if (path.indexOf('\r') != -1) path = path.substring(0, path.indexOf('\r'));
+        return path;
     }
 
     @Override
     public boolean canImport(JComponent component, DataFlavor[] dataFlavors) {
         for (DataFlavor flavor : dataFlavors) {
-            if (flavor.isFlavorJavaFileListType()) {
+            if (flavor.isFlavorJavaFileListType() || flavor.isFlavorTextType()) {
                 return true;
             }
         }
diff --git a/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml b/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
index b9e2c7f..97bc8b1 100644
--- a/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
+++ b/tools/eclipse/features/com.android.ide.eclipse.adt/feature.xml
@@ -134,6 +134,7 @@
       <import plugin="org.eclipse.wst.sse.ui"/>
       <import plugin="org.eclipse.wst.xml.core"/>
       <import plugin="org.eclipse.wst.xml.ui"/>
+      <import plugin="org.eclipse.jdt.junit"/>
    </requires>
 
    <plugin
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath b/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
index c3c8c10..a24fc87 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/.classpath
@@ -10,7 +10,7 @@
 	<classpathentry kind="lib" path="layoutlib_api.jar"/>
 	<classpathentry kind="lib" path="layoutlib_utils.jar"/>
 	<classpathentry kind="lib" path="ninepatch.jar"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
-	<classpathentry combineaccessrules="false" kind="src" path="/SdkUiLib"/>
+	<classpathentry kind="lib" path="sdklib.jar" sourcepath="/SdkLib"/>
+	<classpathentry kind="lib" path="sdkuilib.jar" sourcepath="/SdkUiLib"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
index a464d5c..3750f66 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/META-INF/MANIFEST.MF
@@ -39,10 +39,12 @@
  org.eclipse.wst.sse.core,
  org.eclipse.wst.sse.ui,
  org.eclipse.wst.xml.core,
- org.eclipse.wst.xml.ui
+ org.eclipse.wst.xml.ui,
+ org.eclipse.jdt.junit
 Eclipse-LazyStart: true
 Export-Package: com.android.ide.eclipse.adt,
  com.android.ide.eclipse.adt.build;x-friends:="com.android.ide.eclipse.tests",
+ com.android.ide.eclipse.adt.launch;x-friends:="com.android.ide.eclipse.tests",
  com.android.ide.eclipse.adt.project;x-friends:="com.android.ide.eclipse.tests",
  com.android.ide.eclipse.adt.project.internal;x-friends:="com.android.ide.eclipse.tests",
  com.android.ide.eclipse.adt.sdk;x-friends:="com.android.ide.eclipse.tests",
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
index d6c9ac1..4dfcc07 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml
@@ -111,7 +111,7 @@
    <extension
          point="org.eclipse.debug.core.launchConfigurationTypes">
       <launchConfigurationType
-            delegate="com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate"
+            delegate="com.android.ide.eclipse.adt.launch.LaunchConfigDelegate"
             delegateDescription="The Android Application Launcher supports running and debugging remote Android applications on devices or emulators."
             delegateName="Android Launcher"
             id="com.android.ide.eclipse.adt.debug.LaunchConfigType"
@@ -132,7 +132,7 @@
    <extension
          point="org.eclipse.debug.ui.launchConfigurationTabGroups">
       <launchConfigurationTabGroup
-            class="com.android.ide.eclipse.adt.debug.ui.LaunchConfigTabGroup"
+            class="com.android.ide.eclipse.adt.launch.LaunchConfigTabGroup"
             description="Android Application"
             id="com.android.ide.eclipse.adt.debug.LaunchConfigTabGroup"
             type="com.android.ide.eclipse.adt.debug.LaunchConfigType"/>
@@ -140,8 +140,8 @@
    <extension
          point="org.eclipse.debug.ui.launchShortcuts">
       <shortcut
-            category="com.android.ide.eclipse.adt.debug.LaunchConfigType"
-            class="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut"
+            category="com.android.ide.eclipse.adt.launch.LaunchConfigType"
+            class="com.android.ide.eclipse.adt.launch.LaunchShortcut"
             icon="icons/android.png"
             id="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut"
             label="Android Application"
@@ -220,12 +220,6 @@
                value="com.android.ide.eclipse.adt.AndroidNature">
          </filter>
          <action
-               class="com.android.ide.eclipse.adt.project.CreateAidlImportAction"
-               enablesFor="1"
-               id="com.android.ide.eclipse.adt.project.CreateAidlImportAction"
-               label="Create Aidl preprocess file for Parcelable classes"
-               menubarPath="com.android.ide.eclipse.adt.AndroidTools/group1"/>
-         <action
                class="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
                enablesFor="1"
                id="com.android.ide.eclipse.adt.project.NewXmlFileWizardAction"
@@ -345,24 +339,24 @@
             name="Debug Android Application"
             description="Debug Android Application"
             categoryId="org.eclipse.debug.ui.category.run"
-            id="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut.debug">
+            id="com.android.ide.eclipse.adt.launch.LaunchShortcut.debug">
       </command>
       <command
             name="Run Android Application"
             description="Run Android Application"
             categoryId="org.eclipse.debug.ui.category.run"
-            id="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut.run">
+            id="com.android.ide.eclipse.adt.launch.LaunchShortcut.run">
       </command>
       <keyBinding
             keySequence="M3+M2+A D"
             contextId="org.eclipse.ui.globalScope"
-            commandId="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut.debug"
+            commandId="com.android.ide.eclipse.adt.launch.LaunchShortcut.debug"
             keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration">
       </keyBinding>
       <keyBinding
             keySequence="M3+M2+A R"
             contextId="org.eclipse.ui.globalScope"
-            commandId="com.android.ide.eclipse.adt.debug.launching.LaunchShortcut.run"
+            commandId="com.android.ide.eclipse.adt.launch.LaunchShortcut.run"
             keyConfigurationId="org.eclipse.ui.defaultAcceleratorConfiguration">
       </keyBinding>
    </extension>
@@ -499,4 +493,15 @@
          </action>
       </actionSet>
    </extension>
+   <extension
+         point="org.eclipse.debug.core.launchDelegates">
+       <launchDelegate
+             delegate="com.android.ide.eclipse.adt.launch.JUnitLaunchConfigDelegate"
+             delegateDescription="Removes the Android JAR from the Bootstrap Classpath"
+             id="com.android.ide.eclipse.adt.launch.JUnitLaunchConfigDelegate.launchAndroidJunit"
+             modes="run,debug"
+             name="Android JUnit"
+             type="org.eclipse.jdt.junit.launchconfig">
+       </launchDelegate>
+   </extension>
 </plugin>
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 61be3e5..48a21d1 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -20,7 +20,7 @@
 import com.android.ddmuilib.StackTracePanel.ISourceRevealer;
 import com.android.ddmuilib.console.DdmConsole;
 import com.android.ddmuilib.console.IDdmConsole;
-import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController;
+import com.android.ide.eclipse.adt.launch.AndroidLaunchController;
 import com.android.ide.eclipse.adt.preferences.BuildPreferencePage;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
 import com.android.ide.eclipse.adt.project.export.ExportWizard;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
index e2e9728..c3d5ba6 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/BaseBuilder.java
@@ -20,15 +20,14 @@
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
 import com.android.ide.eclipse.adt.sdk.LoadStatus;
-import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.ide.eclipse.common.project.XmlErrorHandler;
 import com.android.ide.eclipse.common.project.XmlErrorHandler.XmlErrorListener;
-import com.android.sdklib.IAndroidTarget;
 
 import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -37,8 +36,10 @@
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.jdt.core.IClasspathEntry;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
@@ -892,25 +893,19 @@
             stopBuild("SDK is not loaded yet");
         }
 
-        // check the compiler compliance level.
-        if (ProjectHelper.checkCompilerCompliance(project) !=
-                ProjectHelper.COMPILER_COMPLIANCE_OK) {
-            // we exit silently
-            stopBuild(Messages.Compiler_Compliance_Error);
+        // abort if there are TARGET or ADT type markers
+        IMarker[] markers = project.findMarkers(AdtConstants.MARKER_TARGET,
+                false /*includeSubtypes*/, IResource.DEPTH_ZERO);
+        
+        if (markers.length > 0) {
+            stopBuild("");
         }
-
-        // Check that the SDK directory has been setup.
-        String osSdkFolder = AdtPlugin.getOsSdkFolder();
-
-        if (osSdkFolder == null || osSdkFolder.length() == 0) {
-            stopBuild(Messages.No_SDK_Setup_Error);
-        }
-
-        IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
-        if (projectTarget == null) {
-            // no target. error has been output by the container initializer:
-            // exit silently.
-            stopBuild("Project has no target");
+        
+        markers = project.findMarkers(AdtConstants.MARKER_ADT, false /*includeSubtypes*/,
+                IResource.DEPTH_ZERO);
+        
+        if (markers.length > 0) {
+            stopBuild("");
         }
     }
     
@@ -925,5 +920,22 @@
         throw new CoreException(new Status(IStatus.CANCEL, AdtPlugin.PLUGIN_ID,
                 String.format(error, args)));
     }
-
+    
+    /**
+     * Recursively delete all the derived resources.
+     */
+    protected void removeDerivedResources(IResource resource, IProgressMonitor monitor)
+            throws CoreException {
+        if (resource.exists()) {
+            if (resource.isDerived()) {
+                resource.delete(true, new SubProgressMonitor(monitor, 10));
+            } else if (resource.getType() == IResource.FOLDER) {
+                IFolder folder = (IFolder)resource;
+                IResource[] members = folder.members();
+                for (IResource member : members) {
+                    removeDerivedResources(member, monitor);
+                }
+            }
+        }
+    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
index a0e446c..fb1608c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerBuilder.java
@@ -19,7 +19,6 @@
 import com.android.ide.eclipse.adt.AdtConstants;
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.project.FixLaunchConfig;
-import com.android.ide.eclipse.adt.project.ProjectHelper;
 import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidManifestHelper;
@@ -27,8 +26,8 @@
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.ide.eclipse.common.project.XmlErrorHandler.BasicXmlErrorListener;
 import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
 
-import org.eclipse.core.resources.IContainer;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IMarker;
@@ -36,13 +35,13 @@
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceDelta;
 import org.eclipse.core.resources.IWorkspaceRoot;
-import org.eclipse.core.resources.ResourceAttributes;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
 
@@ -68,13 +67,8 @@
 
     private static final String PROPERTY_PACKAGE = "manifestPackage"; //$NON-NLS-1$
 
-    private static final String PROPERTY_SOURCE_FOLDER =
-        "manifestPackageSourceFolder"; //$NON-NLS-1$
-
     private static final String PROPERTY_COMPILE_RESOURCES = "compileResources"; //$NON-NLS-1$
-
-    static final String PROPERTY_ANDROID_GENERATED = "androidGenerated"; //$NON-NLS-1$
-    static final String PROPERTY_ANDROID_CONFLICT = "androidConflict"; //$NON-NLS-1$
+    private static final String PROPERTY_COMPILE_AIDL = "compileAidl"; //$NON-NLS-1$
 
     /**
      * Single line aidl error<br>
@@ -83,24 +77,58 @@
     private static Pattern sAidlPattern1 = Pattern.compile("^(.+?):(\\d+):\\s(.+)$"); //$NON-NLS-1$
 
     /**
-     * Compile flag. This is set to true if one of the changed/added/removed
-     * file is a resource file. Upon visiting all the delta resources, if
-     * this flag is true, then we know we'll have to compile the resources
-     * into R.java
+     * Data to temporarly store aidl source file information
      */
-    private boolean mCompileResources = false;
+    static class AidlData {
+        IFile aidlFile;
+        IFolder sourceFolder;
+
+        AidlData(IFolder sourceFolder, IFile aidlFile) {
+            this.sourceFolder = sourceFolder;
+            this.aidlFile = aidlFile;
+        }
+        
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            
+            if (obj instanceof AidlData) {
+                AidlData file = (AidlData)obj;
+                return aidlFile.equals(file.aidlFile) && sourceFolder.equals(file.sourceFolder);
+            }
+            
+            return false;
+        }
+    }
+    
+    /**
+     * Resource Compile flag. This flag is reset to false after each successful compilation, and
+     * stored in the project persistent properties. This allows the builder to remember its state
+     * when the project is closed/opened.
+     */
+    private boolean mMustCompileResources = false;
 
     /** List of .aidl files found that are modified or new. */
-    private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
+    private final ArrayList<AidlData> mAidlToCompile = new ArrayList<AidlData>();
 
     /** List of .aidl files that have been removed. */
-    private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
+    private final ArrayList<AidlData> mAidlToRemove = new ArrayList<AidlData>();
 
     /** cache of the java package defined in the manifest */
     private String mManifestPackage;
+    
+    /** Output folder for generated Java File. Created on the Builder init
+     * @see #startupOnInitialize()
+     */
+    private IFolder mGenFolder;
 
-    /** Source folder containing the java package defined in the manifest. */
-    private IFolder mManifestPackageSourceFolder;
+    /**
+     * Progress monitor used at the end of every build to refresh the content of the 'gen' folder
+     * and set the generated files as derived.
+     */
+    private DerivedProgressMonitor mDerivedProgressMonitor;
 
     /**
      * Progress monitor waiting the end of the process to set a persistent value
@@ -109,91 +137,36 @@
      * to be known by eclipse, before we can call <code>resource.setPersistentProperty</code> on
      * a new file.
      */
-    private static class RefreshProgressMonitor implements IProgressMonitor {
-        private boolean mCancelled = false;
-        private IFile mNewFile;
-        private IFile mSource;
-        private boolean mDoneExecuted = false;
-        public RefreshProgressMonitor(IFile newFile, IFile source) {
-            mNewFile = newFile;
-            mSource = source;
-        }
-
-        public void beginTask(String name, int totalWork) {
-        }
-
-        public void done() {
-            if (mDoneExecuted == false) {
-                mDoneExecuted = true;
-                if (mNewFile.exists()) {
-                    ProjectHelper.saveResourceProperty(mNewFile, PROPERTY_ANDROID_GENERATED,
-                            mSource);
-                    try {
-                        mNewFile.setDerived(true);
-                    } catch (CoreException e) {
-                        // This really shouldn't happen since we check that the resource exist.
-                        // Worst case scenario, the resource isn't marked as derived.
-                    }
-                }
-            }
-        }
-
-        public void internalWorked(double work) {
-        }
-
-        public boolean isCanceled() {
-            return mCancelled;
-        }
-
-        public void setCanceled(boolean value) {
-            mCancelled = value;
-        }
-
-        public void setTaskName(String name) {
-        }
-
-        public void subTask(String name) {
-        }
-
-        public void worked(int work) {
-        }
-    }
-
-    /**
-     * Progress Monitor setting up to two files as derived once their parent is refreshed.
-     * This is used as ProgressMonitor to refresh the R.java/Manifest.java parent (to display
-     * the newly created files in the package explorer).
-     */
     private static class DerivedProgressMonitor implements IProgressMonitor {
         private boolean mCancelled = false;
-        private IFile mFile1;
-        private IFile mFile2;
-        private boolean mDoneExecuted = false;
-        public DerivedProgressMonitor(IFile file1, IFile file2) {
-            mFile1 = file1;
-            mFile2 = file2;
+        private final ArrayList<IFile> mFileList = new ArrayList<IFile>();
+        private boolean mDone = false;
+        public DerivedProgressMonitor() {
+        }
+        
+        void addFile(IFile file) {
+            mFileList.add(file);
+        }
+        
+        void reset() {
+            mFileList.clear();
+            mDone = false;
         }
 
         public void beginTask(String name, int totalWork) {
         }
 
         public void done() {
-            if (mDoneExecuted == false) {
-                if (mFile1 != null && mFile1.exists()) {
-                    mDoneExecuted = true;
-                    try {
-                        mFile1.setDerived(true);
-                    } catch (CoreException e) {
-                        // This really shouldn't happen since we check that the resource edit.
-                        // Worst case scenario, the resource isn't marked as derived.
-                    }
-                }
-                if (mFile2 != null && mFile2.exists()) {
-                    try {
-                        mFile2.setDerived(true);
-                    } catch (CoreException e) {
-                        // This really shouldn't happen since we check that the resource edit.
-                        // Worst case scenario, the resource isn't marked as derived.
+            if (mDone == false) {
+                mDone = true;
+                for (IFile file : mFileList) {
+                    if (file.exists()) {
+                        try {
+                            file.setDerived(true);
+                        } catch (CoreException e) {
+                            // This really shouldn't happen since we check that the resource exist.
+                            // Worst case scenario, the resource isn't marked as derived.
+                        }
                     }
                 }
             }
@@ -229,322 +202,306 @@
     @Override
     protected IProject[] build(int kind, Map args, IProgressMonitor monitor)
             throws CoreException {
-        // First thing we do is go through the resource delta to not
-        // lose it if we have to abort the build for any reason.
+        try {
+            mDerivedProgressMonitor.reset();
 
-        // get the project objects
-        IProject project = getProject();
-        
-        // Top level check to make sure the build can move forward.
-        abortOnBadSetup(project);
-        
-        IJavaProject javaProject = JavaCore.create(project);
-        IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
-
-        // now we need to get the classpath list
-        ArrayList<IPath> sourceList = BaseProjectHelper.getSourceClasspaths(javaProject);
-
-        PreCompilerDeltaVisitor dv = null;
-        String javaPackage = null;
-
-        if (kind == FULL_BUILD) {
-            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                    Messages.Start_Full_Pre_Compiler);
-            mCompileResources = true;
-            buildAidlCompilationList(project, sourceList);
-        } else {
-            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                    Messages.Start_Inc_Pre_Compiler);
-
-            // Go through the resources and see if something changed.
-            // Even if the mCompileResources flag is true from a previously aborted
-            // build, we need to go through the Resource delta to get a possible
-            // list of aidl files to compile/remove.
-            IResourceDelta delta = getDelta(project);
-            if (delta == null) {
-                mCompileResources = true;
-                buildAidlCompilationList(project, sourceList);
+            // First thing we do is go through the resource delta to not
+            // lose it if we have to abort the build for any reason.
+    
+            // get the project objects
+            IProject project = getProject();
+            
+            // Top level check to make sure the build can move forward.
+            abortOnBadSetup(project);
+            
+            IJavaProject javaProject = JavaCore.create(project);
+            IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
+    
+            // now we need to get the classpath list
+            ArrayList<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(
+                    javaProject);
+            
+            PreCompilerDeltaVisitor dv = null;
+            String javaPackage = null;
+    
+            if (kind == FULL_BUILD) {
+                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                        Messages.Start_Full_Pre_Compiler);
+                mMustCompileResources = true;
+                buildAidlCompilationList(project, sourceFolderPathList);
             } else {
-                dv = new PreCompilerDeltaVisitor(this, sourceList);
-                delta.accept(dv);
-
-                // record the state
-                mCompileResources |= dv.getCompileResources();
-                
-                // handle aidl modification
-                if (dv.getFullAidlRecompilation()) {
-                    buildAidlCompilationList(project, sourceList);
+                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                        Messages.Start_Inc_Pre_Compiler);
+    
+                // Go through the resources and see if something changed.
+                // Even if the mCompileResources flag is true from a previously aborted
+                // build, we need to go through the Resource delta to get a possible
+                // list of aidl files to compile/remove.
+                IResourceDelta delta = getDelta(project);
+                if (delta == null) {
+                    mMustCompileResources = true;
+                    buildAidlCompilationList(project, sourceFolderPathList);
                 } else {
+                    dv = new PreCompilerDeltaVisitor(this, sourceFolderPathList);
+                    delta.accept(dv);
+    
+                    // record the state
+                    mMustCompileResources |= dv.getCompileResources();
+                    
+                    // handle aidl modification, and update mMustCompileAidl
                     mergeAidlFileModifications(dv.getAidlToCompile(),
                             dv.getAidlToRemove());
+                    
+                    // get the java package from the visitor
+                    javaPackage = dv.getManifestPackage();
                 }
-                
-                // get the java package from the visitor
-                javaPackage = dv.getManifestPackage();
             }
-        }
-
-        // store the build status in the persistent storage
-        saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , mCompileResources);
-        // TODO also needs to store the list of aidl to compile/remove
-
-        // if there was some XML errors, we just return w/o doing
-        // anything since we've put some markers in the files anyway.
-        if (dv != null && dv.mXmlError) {
-            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                    Messages.Xml_Error);
-
-            // This interrupts the build. The next builders will not run.
-            stopBuild(Messages.Xml_Error);
-        }
-
-
-        // get the manifest file
-        IFile manifest = AndroidManifestHelper.getManifest(project);
-
-        if (manifest == null) {
-            String msg = String.format(Messages.s_File_Missing,
-                    AndroidConstants.FN_ANDROID_MANIFEST);
-            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
-            markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
-            // This interrupts the build. The next builders will not run.
-            stopBuild(msg);
-        }
-
-        // lets check the XML of the manifest first, if that hasn't been done by the
-        // resource delta visitor yet.
-        if (dv == null || dv.getCheckedManifestXml() == false) {
-            BasicXmlErrorListener errorListener = new BasicXmlErrorListener();
-            AndroidManifestParser parser = BaseProjectHelper.parseManifestForError(manifest,
-                    errorListener);
-            
-            if (errorListener.mHasXmlError == true) {
-                // there was an error in the manifest, its file has been marked,
-                // by the XmlErrorHandler.
-                // We return;
-                String msg = String.format(Messages.s_Contains_Xml_Error,
+    
+            // store the build status in the persistent storage
+            saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES , mMustCompileResources);
+    
+            // if there was some XML errors, we just return w/o doing
+            // anything since we've put some markers in the files anyway.
+            if (dv != null && dv.mXmlError) {
+                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                        Messages.Xml_Error);
+    
+                // This interrupts the build. The next builders will not run.
+                stopBuild(Messages.Xml_Error);
+            }
+    
+    
+            // get the manifest file
+            IFile manifest = AndroidManifestHelper.getManifest(project);
+    
+            if (manifest == null) {
+                String msg = String.format(Messages.s_File_Missing,
                         AndroidConstants.FN_ANDROID_MANIFEST);
                 AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
-
+                markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+    
                 // This interrupts the build. The next builders will not run.
                 stopBuild(msg);
             }
-            
-            // get the java package from the parser
-            javaPackage = parser.getPackage();
-        }
-
-        if (javaPackage == null || javaPackage.length() == 0) {
-            // looks like the AndroidManifest file isn't valid.
-            String msg = String.format(Messages.s_Doesnt_Declare_Package_Error,
-                    AndroidConstants.FN_ANDROID_MANIFEST);
-            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                    msg);
-
-            // This interrupts the build. The next builders will not run.
-            stopBuild(msg);
-        }
-
-        // at this point we have the java package. We need to make sure it's not a different package
-        // than the previous one that were built.
-        if (javaPackage.equals(mManifestPackage) == false) {
-            // The manifest package has changed, the user may want to update
-            // the launch configuration
-            if (mManifestPackage != null) {
-                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                        Messages.Checking_Package_Change);
-
-                FixLaunchConfig flc = new FixLaunchConfig(project, mManifestPackage, javaPackage);
-                flc.start();
+    
+            // lets check the XML of the manifest first, if that hasn't been done by the
+            // resource delta visitor yet.
+            if (dv == null || dv.getCheckedManifestXml() == false) {
+                BasicXmlErrorListener errorListener = new BasicXmlErrorListener();
+                AndroidManifestParser parser = BaseProjectHelper.parseManifestForError(manifest,
+                        errorListener);
+                
+                if (errorListener.mHasXmlError == true) {
+                    // there was an error in the manifest, its file has been marked,
+                    // by the XmlErrorHandler.
+                    // We return;
+                    String msg = String.format(Messages.s_Contains_Xml_Error,
+                            AndroidConstants.FN_ANDROID_MANIFEST);
+                    AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, msg);
+    
+                    // This interrupts the build. The next builders will not run.
+                    stopBuild(msg);
+                }
+                
+                // get the java package from the parser
+                javaPackage = parser.getPackage();
             }
-
-            // now we delete the generated classes from their previous location
-            deleteObsoleteGeneratedClass(AndroidConstants.FN_RESOURCE_CLASS,
-                    mManifestPackageSourceFolder, mManifestPackage);
-            deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
-                    mManifestPackageSourceFolder, mManifestPackage);
-
-            // record the new manifest package, and save it.
-            mManifestPackage = javaPackage;
-            saveProjectStringProperty(PROPERTY_PACKAGE, mManifestPackage);
-        }
-
-        if (mCompileResources) {
-            // we need to figure out where to store the R class.
-            // get the parent folder for R.java and update mManifestPackageSourceFolder
-            IFolder packageFolder = getManifestPackageFolder(project, sourceList);
-
-            // at this point, either we have found the package or not.
-            // if we haven't well it's time to tell the user and abort
-            if (mManifestPackageSourceFolder == null) {
-                // mark the manifest file
-                String message = String.format(Messages.Package_s_Doesnt_Exist_Error,
-                        mManifestPackage);
-                BaseProjectHelper.addMarker(manifest, AndroidConstants.MARKER_AAPT_COMPILE, message,
-                        IMarker.SEVERITY_ERROR);
-                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project, message);
-
-                // abort
+    
+            if (javaPackage == null || javaPackage.length() == 0) {
+                // looks like the AndroidManifest file isn't valid.
+                String msg = String.format(Messages.s_Doesnt_Declare_Package_Error,
+                        AndroidConstants.FN_ANDROID_MANIFEST);
+                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                        msg);
+    
                 // This interrupts the build. The next builders will not run.
-                stopBuild(message);
+                stopBuild(msg);
             }
-
-
-            // found the folder in which to write the stuff
-
-            // get the resource folder
-            IFolder resFolder = project.getFolder(AndroidConstants.WS_RESOURCES);
-
-            // get the file system path
-            IPath outputLocation = mManifestPackageSourceFolder.getLocation();
-            IPath resLocation = resFolder.getLocation();
-            IPath manifestLocation = manifest.getLocation();
-
-            // those locations have to exist for us to do something!
-            if (outputLocation != null && resLocation != null
-                    && manifestLocation != null) {
-                String osOutputPath = outputLocation.toOSString();
-                String osResPath = resLocation.toOSString();
-                String osManifestPath = manifestLocation.toOSString();
-
-                // remove the aapt markers
-                removeMarkersFromFile(manifest, AndroidConstants.MARKER_AAPT_COMPILE);
-                removeMarkersFromContainer(resFolder, AndroidConstants.MARKER_AAPT_COMPILE);
-
-                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                        Messages.Preparing_Generated_Files);
-
-                // since the R.java file may be already existing in read-only
-                // mode we need to make it readable so that aapt can overwrite
-                // it
-                IFile rJavaFile = packageFolder.getFile(AndroidConstants.FN_RESOURCE_CLASS);
-                prepareFileForExternalModification(rJavaFile);
-
-                // do the same for the Manifest.java class
-                IFile manifestJavaFile = packageFolder.getFile(AndroidConstants.FN_MANIFEST_CLASS);
-                prepareFileForExternalModification(manifestJavaFile);
-
-                // we actually need to delete the manifest.java as it may become empty and in this
-                // case aapt doesn't generate an empty one, but instead doesn't touch it.
-                manifestJavaFile.delete(true, null);
-
-                // launch aapt: create the command line
-                ArrayList<String> array = new ArrayList<String>();
-                array.add(projectTarget.getPath(IAndroidTarget.AAPT));
-                array.add("package"); //$NON-NLS-1$
-                array.add("-m"); //$NON-NLS-1$
-                if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
-                    array.add("-v"); //$NON-NLS-1$
+    
+            // at this point we have the java package. We need to make sure it's not a different
+            // package than the previous one that were built.
+            if (javaPackage.equals(mManifestPackage) == false) {
+                // The manifest package has changed, the user may want to update
+                // the launch configuration
+                if (mManifestPackage != null) {
+                    AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                            Messages.Checking_Package_Change);
+    
+                    FixLaunchConfig flc = new FixLaunchConfig(project, mManifestPackage,
+                            javaPackage);
+                    flc.start();
                 }
-                array.add("-J"); //$NON-NLS-1$
-                array.add(osOutputPath);
-                array.add("-M"); //$NON-NLS-1$
-                array.add(osManifestPath);
-                array.add("-S"); //$NON-NLS-1$
-                array.add(osResPath);
-                array.add("-I"); //$NON-NLS-1$
-                array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
-
-                if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
-                    StringBuilder sb = new StringBuilder();
-                    for (String c : array) {
-                        sb.append(c);
-                        sb.append(' ');
+    
+                // now we delete the generated classes from their previous location
+                deleteObsoleteGeneratedClass(AndroidConstants.FN_RESOURCE_CLASS,
+                        mManifestPackage);
+                deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
+                        mManifestPackage);
+    
+                // record the new manifest package, and save it.
+                mManifestPackage = javaPackage;
+                saveProjectStringProperty(PROPERTY_PACKAGE, mManifestPackage);
+            }
+    
+            if (mMustCompileResources) {
+                // we need to figure out where to store the R class.
+                // get the parent folder for R.java and update mManifestPackageSourceFolder
+                IFolder packageFolder = getGenManifestPackageFolder(project);
+    
+                // get the resource folder
+                IFolder resFolder = project.getFolder(AndroidConstants.WS_RESOURCES);
+    
+                // get the file system path
+                IPath outputLocation = mGenFolder.getLocation();
+                IPath resLocation = resFolder.getLocation();
+                IPath manifestLocation = manifest.getLocation();
+    
+                // those locations have to exist for us to do something!
+                if (outputLocation != null && resLocation != null
+                        && manifestLocation != null) {
+                    String osOutputPath = outputLocation.toOSString();
+                    String osResPath = resLocation.toOSString();
+                    String osManifestPath = manifestLocation.toOSString();
+    
+                    // remove the aapt markers
+                    removeMarkersFromFile(manifest, AndroidConstants.MARKER_AAPT_COMPILE);
+                    removeMarkersFromContainer(resFolder, AndroidConstants.MARKER_AAPT_COMPILE);
+    
+                    AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                            Messages.Preparing_Generated_Files);
+    
+                    // since the R.java file may be already existing in read-only
+                    // mode we need to make it readable so that aapt can overwrite
+                    // it
+                    IFile rJavaFile = packageFolder.getFile(AndroidConstants.FN_RESOURCE_CLASS);
+    
+                    // do the same for the Manifest.java class
+                    IFile manifestJavaFile = packageFolder.getFile(
+                            AndroidConstants.FN_MANIFEST_CLASS);
+    
+                    // we actually need to delete the manifest.java as it may become empty and
+                    // in this case aapt doesn't generate an empty one, but instead doesn't
+                    // touch it.
+                    manifestJavaFile.delete(true, null);
+    
+                    // launch aapt: create the command line
+                    ArrayList<String> array = new ArrayList<String>();
+                    array.add(projectTarget.getPath(IAndroidTarget.AAPT));
+                    array.add("package"); //$NON-NLS-1$
+                    array.add("-m"); //$NON-NLS-1$
+                    if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
+                        array.add("-v"); //$NON-NLS-1$
                     }
-                    String cmd_line = sb.toString();
-                    AdtPlugin.printToConsole(project, cmd_line);
-                }
-
-                // launch
-                int execError = 1;
-                try {
-                    // launch the command line process
-                    Process process = Runtime.getRuntime().exec(
-                            array.toArray(new String[array.size()]));
-
-                    // list to store each line of stderr
-                    ArrayList<String> results = new ArrayList<String>();
-
-                    // get the output and return code from the process
-                    execError = grabProcessOutput(process, results);
-
-                    // attempt to parse the error output
-                    boolean parsingError = parseAaptOutput(results, project);
-
-                    // if we couldn't parse the output we display it in the console.
-                    if (parsingError) {
-                        if (execError != 0) {
-                            AdtPlugin.printErrorToConsole(project, results.toArray());
-                        } else {
-                            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_NORMAL,
-                                    project, results.toArray());
+                    array.add("-J"); //$NON-NLS-1$
+                    array.add(osOutputPath);
+                    array.add("-M"); //$NON-NLS-1$
+                    array.add(osManifestPath);
+                    array.add("-S"); //$NON-NLS-1$
+                    array.add(osResPath);
+                    array.add("-I"); //$NON-NLS-1$
+                    array.add(projectTarget.getPath(IAndroidTarget.ANDROID_JAR));
+    
+                    if (AdtPlugin.getBuildVerbosity() == AdtConstants.BUILD_VERBOSE) {
+                        StringBuilder sb = new StringBuilder();
+                        for (String c : array) {
+                            sb.append(c);
+                            sb.append(' ');
                         }
+                        String cmd_line = sb.toString();
+                        AdtPlugin.printToConsole(project, cmd_line);
                     }
-
-                    if (execError != 0) {
-                        // if the exec failed, and we couldn't parse the error output (and therefore
-                        // not all files that should have been marked, were marked), we put a
-                        // generic marker on the project and abort.
+    
+                    // launch
+                    int execError = 1;
+                    try {
+                        // launch the command line process
+                        Process process = Runtime.getRuntime().exec(
+                                array.toArray(new String[array.size()]));
+    
+                        // list to store each line of stderr
+                        ArrayList<String> results = new ArrayList<String>();
+    
+                        // get the output and return code from the process
+                        execError = grabProcessOutput(process, results);
+    
+                        // attempt to parse the error output
+                        boolean parsingError = parseAaptOutput(results, project);
+    
+                        // if we couldn't parse the output we display it in the console.
                         if (parsingError) {
-                            markProject(AdtConstants.MARKER_ADT, Messages.Unparsed_AAPT_Errors,
-                                    IMarker.SEVERITY_ERROR);
+                            if (execError != 0) {
+                                AdtPlugin.printErrorToConsole(project, results.toArray());
+                            } else {
+                                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_NORMAL,
+                                        project, results.toArray());
+                            }
                         }
-
-                        AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                                Messages.AAPT_Error);
-
-                        // abort if exec failed.
+    
+                        if (execError != 0) {
+                            // if the exec failed, and we couldn't parse the error output
+                            // (and therefore not all files that should have been marked,
+                            // were marked), we put a generic marker on the project and abort.
+                            if (parsingError) {
+                                markProject(AdtConstants.MARKER_ADT, Messages.Unparsed_AAPT_Errors,
+                                        IMarker.SEVERITY_ERROR);
+                            }
+    
+                            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                                    Messages.AAPT_Error);
+    
+                            // abort if exec failed.
+                            // This interrupts the build. The next builders will not run.
+                            stopBuild(Messages.AAPT_Error);
+                        }
+                    } catch (IOException e1) {
+                        // something happen while executing the process,
+                        // mark the project and exit
+                        String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
+                        markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+    
                         // This interrupts the build. The next builders will not run.
-                        stopBuild(Messages.AAPT_Error);
+                        stopBuild(msg);
+                    } catch (InterruptedException e) {
+                        // we got interrupted waiting for the process to end...
+                        // mark the project and exit
+                        String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
+                        markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
+    
+                        // This interrupts the build. The next builders will not run.
+                        stopBuild(msg);
                     }
-                } catch (IOException e1) {
-                    // something happen while executing the process,
-                    // mark the project and exit
-                    String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
-                    markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
-                    // This interrupts the build. The next builders will not run.
-                    stopBuild(msg);
-                } catch (InterruptedException e) {
-                    // we got interrupted waiting for the process to end...
-                    // mark the project and exit
-                    String msg = String.format(Messages.AAPT_Exec_Error, array.get(0));
-                    markProject(AdtConstants.MARKER_ADT, msg, IMarker.SEVERITY_ERROR);
-
-                    // This interrupts the build. The next builders will not run.
-                    stopBuild(msg);
+    
+                    // if the return code was OK, we refresh the folder that
+                    // contains R.java to force a java recompile.
+                    if (execError == 0) {
+                        // now add the R.java/Manifest.java to the list of file to be marked
+                        // as derived.
+                        mDerivedProgressMonitor.addFile(rJavaFile);
+                        mDerivedProgressMonitor.addFile(manifestJavaFile);
+                        
+                        // build has been done. reset the state of the builder
+                        mMustCompileResources = false;
+    
+                        // and store it
+                        saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES,
+                                mMustCompileResources);
+                    }
                 }
-
-                // if the return code was OK, we refresh the folder that
-                // contains R.java to force a java recompile.
-                if (execError == 0) {
-                    // now set the R.java/Manifest.java file as read only.
-                    finishJavaFilesAfterExternalModification(rJavaFile, manifestJavaFile);
-
-                    // build has been done. reset the state of the builder
-                    mCompileResources = false;
-
-                    // and store it
-                    saveProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, mCompileResources);
-                }
+            } else {
+                // nothing to do
             }
-        } else {
-            // nothing to do
-        }
-
-        // now handle the aidl stuff.
-        // look for a preprocessed aidl file
-        IResource projectAidl = project.findMember("project.aidl"); //$NON-NLS-1$
-        String folderAidlPath = null;
-        if (projectAidl != null && projectAidl.exists()) {
-            folderAidlPath = projectAidl.getLocation().toOSString();
-        }
-        boolean aidlStatus = handleAidl(projectTarget, sourceList, folderAidlPath, monitor);
-
-        if (aidlStatus == false && mCompileResources == false) {
-            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                    Messages.Nothing_To_Compile);
+    
+            // now handle the aidl stuff.
+            boolean aidlStatus = handleAidl(projectTarget, sourceFolderPathList, monitor);
+    
+            if (aidlStatus == false && mMustCompileResources == false) {
+                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                        Messages.Nothing_To_Compile);
+            }
+        } finally {
+            // refresh the 'gen' source folder. Once this is done with the custom progress
+            // monitor to mark all new files as derived
+            mGenFolder.refreshLocal(IResource.DEPTH_INFINITE, mDerivedProgressMonitor);
         }
 
         return null;
@@ -557,67 +514,57 @@
         AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, getProject(),
                 Messages.Removing_Generated_Classes);
 
-        // check if we have the R.java info already.
-        if (mManifestPackageSourceFolder != null && mManifestPackage != null) {
-            deleteObsoleteGeneratedClass(AndroidConstants.FN_RESOURCE_CLASS,
-                    mManifestPackageSourceFolder, mManifestPackage);
-            deleteObsoleteGeneratedClass(AndroidConstants.FN_MANIFEST_CLASS,
-                    mManifestPackageSourceFolder, mManifestPackage);
-        }
-        
-        // FIXME: delete all java generated from aidl.
+        // remove all the derived resources from the 'gen' source folder.
+        removeDerivedResources(mGenFolder, monitor);
     }
 
     @Override
     protected void startupOnInitialize() {
         super.startupOnInitialize();
+        
+        mDerivedProgressMonitor = new DerivedProgressMonitor();
+        
+        IProject project = getProject();
 
         // load the previous IFolder and java package.
         mManifestPackage = loadProjectStringProperty(PROPERTY_PACKAGE);
-        IResource resource = loadProjectResourceProperty(PROPERTY_SOURCE_FOLDER);
-        if (resource instanceof IFolder) {
-            mManifestPackageSourceFolder = (IFolder)resource;
-        }
+        
+        // get the source folder in which all the Java files are created
+        mGenFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
 
-        // Load the current compile flag. We ask for true if not found to force a
+        // Load the current compile flags. We ask for true if not found to force a
         // recompile.
-        mCompileResources = loadProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, true);
+        mMustCompileResources = loadProjectBooleanProperty(PROPERTY_COMPILE_RESOURCES, true);
+        boolean mustCompileAidl = loadProjectBooleanProperty(PROPERTY_COMPILE_AIDL, true);
+        
+        // if we stored that we have to compile some aidl, we build the list that will compile them
+        // all
+        if (mustCompileAidl) {
+            IJavaProject javaProject = JavaCore.create(project);
+            ArrayList<IPath> sourceFolderPathList = BaseProjectHelper.getSourceClasspaths(
+                    javaProject);
+            
+            buildAidlCompilationList(project, sourceFolderPathList);
+        }
     }
 
     /**
      * Delete the a generated java class associated with the specified java package.
      * @param filename Name of the generated file to remove.
-     * @param sourceFolder The source Folder containing the old java package.
      * @param javaPackage the old java package
      */
-    private void deleteObsoleteGeneratedClass(String filename, IFolder sourceFolder,
-            String javaPackage) {
-        if (sourceFolder == null || javaPackage == null) {
+    private void deleteObsoleteGeneratedClass(String filename, String javaPackage) {
+        if (javaPackage == null) {
             return;
         }
-
-        // convert the java package into path
-        String[] segments = javaPackage.split(AndroidConstants.RE_DOT);
-
-        StringBuilder path = new StringBuilder();
-        for (String s : segments) {
-           path.append(AndroidConstants.WS_SEP_CHAR);
-           path.append(s);
-        }
-
-        // appends the name of the generated file
-        path.append(AndroidConstants.WS_SEP_CHAR);
-        path.append(filename);
-
-        Path iPath = new Path(path.toString());
+        
+        IPath packagePath = getJavaPackagePath(javaPackage);
+        IPath iPath = packagePath.append(filename);
 
         // Find a matching resource object.
-        IResource javaFile = sourceFolder.findMember(iPath);
+        IResource javaFile = mGenFolder.findMember(iPath);
         if (javaFile != null && javaFile.exists() && javaFile.getType() == IResource.FILE) {
             try {
-                // remove the read-only tag
-                prepareFileForExternalModification((IFile)javaFile);
-
                 // delete
                 javaFile.delete(true, null);
 
@@ -626,7 +573,8 @@
 
             } catch (CoreException e) {
                 // failed to delete it, the user will have to delete it manually.
-                String message = String.format(Messages.Delete_Obsolete_Error, path);
+                String message = String.format(Messages.Delete_Obsolete_Error,
+                        javaFile.getFullPath());
                 IProject project = getProject();
                 AdtPlugin.printErrorToConsole(project, message);
                 AdtPlugin.printErrorToConsole(project, e.getMessage());
@@ -635,94 +583,38 @@
     }
 
     /**
-     * Looks for the folder containing the package defined in the manifest. It looks in the
-     * list of source folders for the one containing folders matching the package defined in the
-     * manifest (from the field <code>mManifestPackage</code>). It returns the final folder, which
-     * will contain the R class, and update the field <code>mManifestPackageSourceFolder</code>
-     * to be the source folder containing the full package.
+     * Creates a relative {@link IPath} from a java package.
+     * @param javaPackageName the java package.
+     */
+    private IPath getJavaPackagePath(String javaPackageName) {
+        // convert the java package into path
+        String[] segments = javaPackageName.split(AndroidConstants.RE_DOT);
+
+        StringBuilder path = new StringBuilder();
+        for (String s : segments) {
+           path.append(AndroidConstants.WS_SEP_CHAR);
+           path.append(s);
+        }
+        
+        return new Path(path.toString());
+    }
+    
+    /**
+     * Returns an {@link IFolder} (located inside the 'gen' source folder), that matches the
+     * package defined in the manifest. This {@link IFolder} may not actually exist
+     * (aapt will create it anyway).
      * @param project The project.
-     * @param sourceList The list of source folders for the project.
-     * @return the package that will contain the R class or null if the folder was not found.
+     * @return the {@link IFolder} that will contain the R class or null if the folder was not found.
      * @throws CoreException
      */
-    private IFolder getManifestPackageFolder(IProject project, ArrayList<IPath> sourceList)
+    private IFolder getGenManifestPackageFolder(IProject project)
             throws CoreException {
-        // split the package in segments
-        String[] packageSegments = mManifestPackage.split(AndroidConstants.RE_DOT);
-
-        // we look for 2 folders.
-        // 1. The source folder that contains the full java package.
-        // we will store the folder in the field mJavaSourceFolder, for reuse during
-        IFolder manifestPackageSourceFolder = null;
-        // subsequent builds. This is the folder we will give to aapt.
-        // 2. The folder actually containing the R.java files. We need this one to do a refresh
-        IFolder packageFolder = null;
-
-        for (IPath iPath : sourceList) {
-            int packageSegmentIndex = 0;
-
-            // the path is relative to the workspace. We ignore the first segment,
-            // when getting the resource from the IProject object.
-            IResource classpathEntry = project.getFolder(iPath.removeFirstSegments(1));
-
-            if (classpathEntry instanceof IFolder) {
-                IFolder classpathFolder = (IFolder)classpathEntry;
-                IFolder folder = classpathFolder;
-
-                boolean failed = false;
-                while (failed == false
-                        && packageSegmentIndex < packageSegments.length) {
-
-                    // loop on that folder content looking for folders
-                    // that match the package
-                    // defined in AndroidManifest.xml
-
-                    // get the folder content
-                    IResource[] content = folder.members();
-
-                    // this is the segment we look for
-                    String segment = packageSegments[packageSegmentIndex];
-
-                    // did we find it at this level
-                    boolean found = false;
-
-                    for (IResource r : content) {
-                        // look for the java package segment
-                        if (r instanceof IFolder) {
-                            if (r.getName().equals(segment)) {
-                                // we need to skip to the next one
-                                folder = (IFolder)r;
-                                packageSegmentIndex++;
-                                found = true;
-                                break;
-                            }
-                        }
-                    }
-
-                    // if we didn't find it at this level we just fail.
-                    if (found == false) {
-                        failed = true;
-                    }
-                }
-
-                // if we didn't fail then we found it. no point in
-                // looping through the rest
-                // or the classpathEntry
-                if (failed == false) {
-                    // save the target folder reference
-                    manifestPackageSourceFolder = classpathFolder;
-                    packageFolder = folder;
-                    break;
-                }
-            }
-        }
-
-        // save the location of the folder into the persistent storage
-        if (manifestPackageSourceFolder != mManifestPackageSourceFolder) {
-            mManifestPackageSourceFolder = manifestPackageSourceFolder;
-            saveProjectResourceProperty(PROPERTY_SOURCE_FOLDER, mManifestPackageSourceFolder);
-        }
-        return packageFolder;
+        // get the path for the package
+        IPath packagePath = getJavaPackagePath(mManifestPackage);
+        
+        // get a folder for this path under the 'gen' source folder, and return it.
+        // This IFolder may not reference an actual existing folder.
+        return mGenFolder.getFolder(packagePath);
     }
 
     /**
@@ -730,27 +622,22 @@
      * created from aidl files that are now gone.
      * @param projectTarget Target of the project
      * @param sourceFolders the list of source folders, relative to the workspace.
-     * @param folderAidlPath 
      * @param monitor the projess monitor
      * @returns true if it did something
      * @throws CoreException
      */
     private boolean handleAidl(IAndroidTarget projectTarget, ArrayList<IPath> sourceFolders,
-            String folderAidlPath, IProgressMonitor monitor) throws CoreException {
+            IProgressMonitor monitor) throws CoreException {
         if (mAidlToCompile.size() == 0 && mAidlToRemove.size() == 0) {
             return false;
         }
-        
 
         // create the command line
-        String[] command = new String[4 + sourceFolders.size() + (folderAidlPath != null ? 1 : 0)];
+        String[] command = new String[4 + sourceFolders.size()];
         int index = 0;
-        int aidlIndex;
         command[index++] = projectTarget.getPath(IAndroidTarget.AIDL);
-        command[aidlIndex = index++] = "-p"; //$NON-NLS-1$
-        if (folderAidlPath != null) {
-            command[index++] = "-p" + folderAidlPath; //$NON-NLS-1$
-        }
+        command[index++] = "-p" + Sdk.getCurrent().getTarget(getProject()).getPath( //$NON-NLS-1$
+                IAndroidTarget.ANDROID_AIDL);
         
         // since the path are relative to the workspace and not the project itself, we need
         // the workspace root.
@@ -761,81 +648,44 @@
         }
 
         // list of files that have failed compilation.
-        ArrayList<IFile> stillNeedCompilation = new ArrayList<IFile>();
+        ArrayList<AidlData> stillNeedCompilation = new ArrayList<AidlData>();
 
         // if an aidl file is being removed before we managed to compile it, it'll be in
         // both list. We *need* to remove it from the compile list or it'll never go away.
-        for (IFile aidlFile : mAidlToRemove) {
+        for (AidlData aidlFile : mAidlToRemove) {
             int pos = mAidlToCompile.indexOf(aidlFile);
             if (pos != -1) {
                 mAidlToCompile.remove(pos);
             }
         }
-        
+
         // loop until we've compile them all
-        for (IFile aidlFile : mAidlToCompile) {
+        for (AidlData aidlData : mAidlToCompile) {
             // Remove the AIDL error markers from the aidl file
-            removeMarkersFromFile(aidlFile, AndroidConstants.MARKER_AIDL);
+            removeMarkersFromFile(aidlData.aidlFile, AndroidConstants.MARKER_AIDL);
 
-            // get the path
-            IPath iPath = aidlFile.getLocation();
-            String osPath = iPath.toOSString();
-
-            // get the parent container
-            IContainer parentContainer = aidlFile.getParent();
-
-            // replace the extension in both the full path and the
-            // last segment
-            String osJavaPath = osPath.replaceAll(AndroidConstants.RE_AIDL_EXT,
-                    AndroidConstants.DOT_JAVA);
-            String javaName = aidlFile.getName().replaceAll(AndroidConstants.RE_AIDL_EXT,
-                    AndroidConstants.DOT_JAVA);
-
-            // check if we can compile it, or if there is a conflict with a java file
-            boolean conflict = ProjectHelper.loadBooleanProperty(aidlFile,
-                    PROPERTY_ANDROID_CONFLICT, false);
-            if (conflict) {
-                String msg = String.format(Messages.AIDL_Java_Conflict, javaName,
-                        aidlFile.getName());
-
-                // put a marker
-                BaseProjectHelper.addMarker(aidlFile, AndroidConstants.MARKER_AIDL, msg,
-                        IMarker.SEVERITY_ERROR);
-
-                // output an error
-                AdtPlugin.printErrorToConsole(getProject(), msg);
-
-                stillNeedCompilation.add(aidlFile);
-
-                // move on to next file
-                continue;
-            }
-
-            // get the resource for the java file.
-            Path javaIPath = new Path(javaName);
-            IFile javaFile = parentContainer.getFile(javaIPath);
-
-            // if the file was read-only, this will make it readable.
-            prepareFileForExternalModification(javaFile);
+            // get the path of the source file.
+            IPath sourcePath = aidlData.aidlFile.getLocation();
+            String osSourcePath = sourcePath.toOSString();
+            
+            IFile javaFile = getGenDestinationFile(aidlData, true /*createFolders*/, monitor);
 
             // finish to set the command line.
-            command[aidlIndex] = "-p" + Sdk.getCurrent().getTarget(aidlFile.getProject()).getPath(
-                    IAndroidTarget.ANDROID_AIDL); //$NON-NLS-1$
-            command[index] = osPath;
-            command[index + 1] = osJavaPath;
+            command[index] = osSourcePath;
+            command[index + 1] = javaFile.getLocation().toOSString();
 
             // launch the process
-            if (execAidl(command, aidlFile) == false) {
+            if (execAidl(command, aidlData.aidlFile) == false) {
                 // aidl failed. File should be marked. We add the file to the list
                 // of file that will need compilation again.
-                stillNeedCompilation.add(aidlFile);
+                stillNeedCompilation.add(aidlData);
 
                 // and we move on to the next one.
                 continue;
             } else {
-                // since the exec worked, we refresh the parent, and set the
-                // file as read only.
-                finishFileAfterExternalModification(javaFile, aidlFile);
+                // make sure the file will be marked as derived once we refresh the 'gen' source
+                // folder.
+                mDerivedProgressMonitor.addFile(javaFile);
             }
         }
 
@@ -844,44 +694,68 @@
         mAidlToCompile.addAll(stillNeedCompilation);
 
         // Remove the java files created from aidl files that have been removed.
-        for (IFile aidlFile : mAidlToRemove) {
-            // make the java filename
-            String javaName = aidlFile.getName().replaceAll(
-                    AndroidConstants.RE_AIDL_EXT,
-                    AndroidConstants.DOT_JAVA);
+        for (AidlData aidlData : mAidlToRemove) {
+            IFile javaFile = getGenDestinationFile(aidlData, false /*createFolders*/, monitor);
+            if (javaFile.exists()) {
+                // This confirms the java file was generated by the builder,
+                // we can delete the aidlFile.
+                javaFile.delete(true, null);
 
-            // get the parent container
-            IContainer ic = aidlFile.getParent();
-
-            // and get the IFile corresponding to the java file.
-            IFile javaFile = ic.getFile(new Path(javaName));
-            if (javaFile != null && javaFile.exists() ) {
-                // check if this java file has a persistent data marking it as generated by
-                // the builder.
-                // While we put the aidl path as a resource, internally it's all string anyway.
-                // We use loadStringProperty, because loadResourceProperty tries to match
-                // the string value (a path in this case) with an existing resource, but
-                // the aidl file was deleted, so it would return null, even though the property
-                // existed.
-                String aidlPath = ProjectHelper.loadStringProperty(javaFile,
-                        PROPERTY_ANDROID_GENERATED);
-
-                if (aidlPath != null) {
-                    // This confirms the java file was generated by the builder,
-                    // we can delete the aidlFile.
-                    javaFile.delete(true, null);
-
-                    // Refresh parent.
-                    ic.refreshLocal(IResource.DEPTH_ONE, monitor);
-                }
+                // Refresh parent.
+                javaFile.getParent().refreshLocal(IResource.DEPTH_ONE, monitor);
             }
         }
+
         mAidlToRemove.clear();
 
+        // store the build state. If there are any files that failed to compile, we will
+        // force a full aidl compile on the next project open. (unless a full compilation succeed
+        // before the project is closed/re-opened.)
+        // TODO: Optimize by saving only the files that need compilation
+        saveProjectBooleanProperty(PROPERTY_COMPILE_AIDL , mAidlToCompile.size() > 0);
+
         return true;
     }
 
     /**
+     * Returns the {@link IFile} handle to the destination file for a given aild source file
+     * ({@link AidlData}).
+     * @param aidlData the data for the aidl source file.
+     * @param createFolders whether or not the parent folder of the destination should be created
+     * if it does not exist.
+     * @param monitor the progress monitor
+     * @return the handle to the destination file.
+     * @throws CoreException
+     */
+    private IFile getGenDestinationFile(AidlData aidlData, boolean createFolders,
+            IProgressMonitor monitor) throws CoreException {
+        // build the destination folder path.
+        // Use the path of the source file, except for the path leading to its source folder,
+        // and for the last segment which is the filename.
+        int segmentToSourceFolderCount = aidlData.sourceFolder.getFullPath().segmentCount();
+        IPath packagePath = aidlData.aidlFile.getFullPath().removeFirstSegments(
+                segmentToSourceFolderCount).removeLastSegments(1);
+        Path destinationPath = new Path(packagePath.toString());
+        
+        // get an IFolder for this path. It's relative to the 'gen' folder already
+        IFolder destinationFolder = mGenFolder.getFolder(destinationPath);
+        
+        // create it if needed
+        if (destinationFolder.exists() == false && createFolders) {
+            destinationFolder.create(true /*force*/, true /*local*/,
+                    new SubProgressMonitor(monitor, 10));;
+        }
+        
+        // Build the Java file name from the aidl name.
+        String javaName = aidlData.aidlFile.getName().replaceAll(AndroidConstants.RE_AIDL_EXT,
+                AndroidConstants.DOT_JAVA);
+
+        // get the resource for the java file.
+        IFile javaFile = destinationFolder.getFile(javaName);
+        return javaFile;
+    }
+
+    /**
      * Execute the aidl command line, parse the output, and mark the aidl file
      * with any reported errors.
      * @param command the String array containing the command line to execute.
@@ -933,43 +807,28 @@
      * Goes through the build paths and fills the list of aidl files to compile
      * ({@link #mAidlToCompile}).
      * @param project The project.
-     * @param buildPaths The list of build paths.
+     * @param sourceFolderPathList The list of source folder paths.
      */
     private void buildAidlCompilationList(IProject project,
-            ArrayList<IPath> buildPaths) {
-        for (IPath p : buildPaths) {
-            // Because the path contains the name of the project as well, we
-            // need to remove it, to access the final folder.
-            String[] segments = p.segments();
-            IContainer folder = project;
-            for (int i = 1; i < segments.length; i++) {
-                IResource r = folder.findMember(segments[i]);
-                if (r != null && r.exists() &&
-                        r.getType() == IResource.FOLDER) {
-                    folder = (IContainer)r;
-                } else {
-                    // hmm looks like the build path is corrupted/wrong.
-                    // reset and break
-                    folder = project;
-                    break;
-                }
-            }
-
-            // did we ge a folder?
-            if (folder != project) {
-                // then we scan!
-                scanContainerForAidl(folder);
+            ArrayList<IPath> sourceFolderPathList) {
+        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+        for (IPath sourceFolderPath : sourceFolderPathList) {
+            IFolder sourceFolder = root.getFolder(sourceFolderPath);
+            // we don't look in the 'gen' source folder as there will be no source in there.
+            if (sourceFolder.exists() && sourceFolder.equals(mGenFolder) == false) {
+                scanFolderForAidl(sourceFolder, sourceFolder);
             }
         }
     }
 
     /**
-     * Scans a container and fills the list of aidl files to compile.
-     * @param container The container to scan.
+     * Scans a folder and fills the list of aidl files to compile.
+     * @param sourceFolder the root source folder.
+     * @param container The folder to scan.
      */
-    private void scanContainerForAidl(IContainer container) {
+    private void scanFolderForAidl(IFolder sourceFolder, IFolder folder) {
         try {
-            IResource[] members = container.members();
+            IResource[] members = folder.members();
             for (IResource r : members) {
                 // get the type of the resource
                switch (r.getType()) {
@@ -978,12 +837,12 @@
                        // and that it's an aidl file
                        if (r.exists() &&
                                AndroidConstants.EXT_AIDL.equalsIgnoreCase(r.getFileExtension())) {
-                           mAidlToCompile.add((IFile)r);
+                           mAidlToCompile.add(new AidlData(sourceFolder, (IFile)r));
                        }
                        break;
                    case IResource.FOLDER:
                        // recursively go through children
-                       scanContainerForAidl((IFolder)r);
+                       scanFolderForAidl(sourceFolder, (IFolder)r);
                        break;
                    default:
                        // this would mean it's a project or the workspace root
@@ -1051,13 +910,12 @@
      * @param toCompile List of file to compile
      * @param toRemove List of file to remove
      */
-    private void mergeAidlFileModifications(ArrayList<IFile> toCompile,
-            ArrayList<IFile> toRemove) {
-
+    private void mergeAidlFileModifications(ArrayList<AidlData> toCompile,
+            ArrayList<AidlData> toRemove) {
         // loop through the new toRemove list, and add it to the old one,
         // plus remove any file that was still to compile and that are now
         // removed
-        for (IFile r : toRemove) {
+        for (AidlData r : toRemove) {
             if (mAidlToRemove.indexOf(r) == -1) {
                 mAidlToRemove.add(r);
             }
@@ -1072,7 +930,7 @@
         // Also look for them in the remove list, this would mean that they
         // were removed, then added back, and we shouldn't remove them, just
         // recompile them.
-        for (IFile r : toCompile) {
+        for (AidlData r : toCompile) {
             if (mAidlToCompile.indexOf(r) == -1) {
                 mAidlToCompile.add(r);
             }
@@ -1083,68 +941,4 @@
             }
         }
     }
-
-    /**
-     * Prepare an already existing file for modification. File generated from
-     * command line processed are marked as read-only. This method prepares
-     * them (mark them as read-write) before the command line process is
-     * started. A check is made to be sure the file exists.
-     * @param file The IResource object for the file to prepare.
-     * @throws CoreException
-     */
-    private void prepareFileForExternalModification(IFile file)
-            throws CoreException {
-        // file may not exist yet, so we check that.
-        if (file != null && file.exists()) {
-            // get the attributes.
-            ResourceAttributes ra = file.getResourceAttributes();
-            if (ra != null) {
-                // change the attributes
-                ra.setReadOnly(false);
-
-                // set the new attributes in the file.
-                file.setResourceAttributes(ra);
-            }
-        }
-    }
-
-    /**
-     * Finish a file created/modified by an outside command line process.
-     * The file is marked as modified by Android, and the parent folder is refreshed, so that,
-     * in case the file didn't exist beforehand, the file appears in the package explorer.
-     * @param rFile The R file to "finish".
-     * @param manifestFile The manifest file to "finish".
-     * @throws CoreException
-     */
-    private void finishJavaFilesAfterExternalModification(IFile rFile, IFile manifestFile)
-            throws CoreException {
-        IContainer parent = rFile.getParent();
-
-        IProgressMonitor monitor = new DerivedProgressMonitor(rFile, manifestFile);
-
-        // refresh the parent node in the package explorer. Once this is done the custom progress
-        // monitor will mark them as derived.
-        parent.refreshLocal(IResource.DEPTH_ONE, monitor);
-    }
-
-    /**
-     * Finish a file created/modified by an outside command line process.
-     * The file is marked as modified by Android, and the parent folder is refreshed, so that,
-     * in case the file didn't exist beforehand, the file appears in the package explorer.
-     * @param file The file to "finish".
-     * @param aidlFile The AIDL file to "finish".
-     * @throws CoreException
-     */
-    private void finishFileAfterExternalModification(IFile file, IFile aidlFile)
-            throws CoreException {
-        IContainer parent = file.getParent();
-
-        // we need to add a link to the aidl file.
-        // We need to wait for the refresh of the parent to be done, so we'll do
-        // it in the monitor. This will also set the file as derived.
-        IProgressMonitor monitor = new RefreshProgressMonitor(file, aidlFile);
-
-        // refresh the parent node in the package explorer.
-        parent.refreshLocal(IResource.DEPTH_ONE, monitor);
-    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
index f4778d7..6841830 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/PreCompilerDeltaVisitor.java
@@ -19,7 +19,7 @@
 import com.android.ide.eclipse.adt.AdtConstants;
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.build.BaseBuilder.BaseDeltaVisitor;
-import com.android.ide.eclipse.adt.project.ProjectHelper;
+import com.android.ide.eclipse.adt.build.PreCompilerBuilder.AidlData;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidManifestParser;
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
@@ -31,14 +31,25 @@
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceDelta;
 import org.eclipse.core.resources.IResourceDeltaVisitor;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Path;
 
 import java.util.ArrayList;
 
 /**
  * Resource Delta visitor for the pre-compiler.
+ * <p/>This delta visitor only cares about files that are the source or the result of actions of the
+ * {@link PreCompilerBuilder}:
+ * <ul><li>R.java/Manifest.java generated by compiling the resources</li>
+ * <li>Any Java files generated by <code>aidl</code></li></ul>.
+ * 
+ * Therefore it looks for the following:
+ * <ul><li>Any modification in the resource folder</li>
+ * <li>Removed files from the source folder receiving generated Java files</li>
+ * <li>Any modification to aidl files.</li>
+ * 
  */
 class PreCompilerDeltaVisitor extends BaseDeltaVisitor implements
         IResourceDeltaVisitor {
@@ -53,14 +64,11 @@
     private boolean mCompileResources = false;
 
     /** List of .aidl files found that are modified or new. */
-    private final ArrayList<IFile> mAidlToCompile = new ArrayList<IFile>();
+    private final ArrayList<AidlData> mAidlToCompile = new ArrayList<AidlData>();
 
     /** List of .aidl files that have been removed. */
-    private final ArrayList<IFile> mAidlToRemove = new ArrayList<IFile>();
+    private final ArrayList<AidlData> mAidlToRemove = new ArrayList<AidlData>();
     
-    /** Aidl forced recompilation flag. This is set to true if project.aidl is modified. */
-    private boolean mFullAidlCompilation = false;
-
     /** Manifest check/parsing flag. */
     private boolean mCheckedManifestXml = false;
 
@@ -75,36 +83,36 @@
     private boolean mInRes = false;
 
     /**
-     * In Source folder flag. This allows us to know if we're in a source
-     * folder.
+     * Current Source folder. This allows us to know if we're in a source
+     * folder, and which folder.
      */
-    private boolean mInSrc = false;
+    private IFolder mSourceFolder = null;
 
     /** List of source folders. */
     private ArrayList<IPath> mSourceFolders;
+    private boolean mIsGenSourceFolder = false;
+
+    private IWorkspaceRoot mRoot;
 
 
     public PreCompilerDeltaVisitor(BaseBuilder builder, ArrayList<IPath> sourceFolders) {
         super(builder);
         mSourceFolders = sourceFolders;
+        mRoot = ResourcesPlugin.getWorkspace().getRoot();
     }
 
     public boolean getCompileResources() {
         return mCompileResources;
     }
 
-    public ArrayList<IFile> getAidlToCompile() {
+    public ArrayList<AidlData> getAidlToCompile() {
         return mAidlToCompile;
     }
 
-    public ArrayList<IFile> getAidlToRemove() {
+    public ArrayList<AidlData> getAidlToRemove() {
         return mAidlToRemove;
     }
     
-    public boolean getFullAidlRecompilation() {
-        return mFullAidlCompilation;
-    }
-
     /**
      * Returns whether the manifest file was parsed/checked for error during the resource delta
      * visiting.
@@ -149,11 +157,13 @@
         // since the delta visitor also visits the root we return true if
         // segments.length = 1
         if (segments.length == 1) {
+            // FIXME: check this is an Android project.
             return true;
         } else if (segments.length == 2) {
             // if we are at an item directly under the root directory,
             // then we are not yet in a source or resource folder
-            mInRes = mInSrc = false;
+            mInRes = false;
+            mSourceFolder = null;
 
             if (SdkConstants.FD_RESOURCES.equalsIgnoreCase(segments[1])) {
                 // this is the resource folder that was modified. we want to
@@ -162,7 +172,7 @@
                 // since we're going to visit its children next, we set the
                 // flag
                 mInRes = true;
-                mInSrc = false;
+                mSourceFolder = null;
                 return true;
             } else if (AndroidConstants.FN_ANDROID_MANIFEST.equalsIgnoreCase(segments[1])) {
                 // any change in the manifest could trigger a new R.java
@@ -183,9 +193,6 @@
                 // we don't want to go to the children, not like they are
                 // any for this resource anyway.
                 return false;
-            } else if (AndroidConstants.FN_PROJECT_AIDL.equalsIgnoreCase(segments[1])) {
-                // need to force recompilation of all the aidl files
-                mFullAidlCompilation = true;
             }
         }
 
@@ -198,7 +205,7 @@
         // so first we test if we already know we are in a source or
         // resource folder.
 
-        if (mInSrc) {
+        if (mSourceFolder != null) {
             // if we are in the res folder, we are looking for the following changes:
             // - added/removed/modified aidl files.
             // - missing R.java file
@@ -216,127 +223,81 @@
             // get the modification kind
             int kind = delta.getKind();
 
-            if (kind == IResourceDelta.ADDED) {
-                // we only care about added files (inside the source folders), if they
-                // are aidl files.
+            // we process normal source folder and the 'gen' source folder differently.
+            if (mIsGenSourceFolder) {
+                // this is the generated java file source folder.
+                // - if R.java/Manifest.java are removed/modified, we recompile the resources
+                // - if aidl files are removed/modified, we recompile them.
 
-                // get the extension of the resource
-                String ext = resource.getFileExtension();
+                boolean outputWarning = false;
 
-                if (AndroidConstants.EXT_AIDL.equalsIgnoreCase(ext)) {
-                    // look for an already existing matching java file
-                    String javaName = resource.getName().replaceAll(
-                            AndroidConstants.RE_AIDL_EXT,
-                            AndroidConstants.DOT_JAVA);
+                String fileName = resource.getName();
 
-                    // get the parent container
-                    IContainer ic = resource.getParent();
+                // Special case of R.java/Manifest.java.
+                if (AndroidConstants.FN_RESOURCE_CLASS.equals(fileName) ||
+                        AndroidConstants.FN_MANIFEST_CLASS.equals(fileName)) {
+                    // if it was removed, there's a possibility that it was removed due to a
+                    // package change, or an aidl that was removed, but the only thing
+                    // that will happen is that we'll have an extra build. Not much of a problem.
+                    mCompileResources = true;
 
-                    IFile javaFile = ic.getFile(new Path(javaName));
-                    if (javaFile != null && javaFile.exists()) {
-                        // check if that file was generated by the plugin. Normally those files are
-                        // deleted automatically, but it's better to check.
-                        String aidlPath = ProjectHelper.loadStringProperty(javaFile,
-                                PreCompilerBuilder.PROPERTY_ANDROID_GENERATED);
-                        if (aidlPath == null) {
-                            // mark the aidl file that it cannot be compile just yet
-                            ProjectHelper.saveBooleanProperty(file,
-                                    PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, true);
-                        }
-
-                        // we add it anyway so that we can try to compile it at every compilation
-                        // until the conflict is fixed.
-                        mAidlToCompile.add(file);
-
-                    } else {
-                        // the java file doesn't exist, we can safely add the file to the list
-                        // of files to compile.
-                        mAidlToCompile.add(file);
-                    }
-                }
-
-                return false;
-            }
-
-            // get the filename
-            String fileName = segments[segments.length - 1];
-
-            boolean outputMessage = false;
-
-            // Special case of R.java/Manifest.java.
-            // FIXME: This does not check the package. Any modification of R.java/Manifest.java in another project will trigger a new recompilation of the resources.
-            if (AndroidConstants.FN_RESOURCE_CLASS.equals(fileName) ||
-                    AndroidConstants.FN_MANIFEST_CLASS.equals(fileName)) {
-                // if it was removed, there's a possibility that it was removed due to a
-                // package change, or an aidl that was removed, but the only thing
-                // that will happen is that we'll have an extra build. Not much of a problem.
-                mCompileResources = true;
-
-                // we want a warning
-                outputMessage = true;
-            } else {
-
-                // get the extension of the resource
-                String ext = resource.getFileExtension();
-
-                if (AndroidConstants.EXT_AIDL.equalsIgnoreCase(ext)) {
-                    if (kind == IResourceDelta.REMOVED) {
-                        mAidlToRemove.add(file);
-                    } else {
-                        mAidlToCompile.add(file);
-                    }
+                    // we want a warning
+                    outputWarning = true;
                 } else {
-                    if (kind == IResourceDelta.REMOVED) {
-                        // the file has been removed. we need to check it's a java file and that
-                        // there's a matching aidl file. We can't check its persistent storage
-                        // anymore.
-                        if (AndroidConstants.EXT_JAVA.equalsIgnoreCase(ext)) {
-                            String aidlFile = resource.getName().replaceAll(
-                                    AndroidConstants.RE_JAVA_EXT,
-                                    AndroidConstants.DOT_AIDL);
-
-                            // get the parent container
-                            IContainer ic = resource.getParent();
-
-                            IFile f = ic.getFile(new Path(aidlFile));
-                            if (f != null && f.exists() ) {
-                                // make sure that the aidl file is not in conflict anymore, in
-                                // case the java file was not generated by us.
-                                if (ProjectHelper.loadBooleanProperty(f,
-                                        PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, false)) {
-                                    ProjectHelper.saveBooleanProperty(f,
-                                            PreCompilerBuilder.PROPERTY_ANDROID_CONFLICT, false);
-                                } else {
-                                    outputMessage = true;
-                                }
-                                mAidlToCompile.add(f);
+                    // this has to be a Java file created from an aidl file.
+                    // Look for the source aidl file in all the source folders.
+                    String aidlFileName = fileName.replaceAll(AndroidConstants.RE_JAVA_EXT,
+                            AndroidConstants.DOT_AIDL);
+                    
+                    for (IPath sourceFolderPath : mSourceFolders) {
+                        // do not search in the current source folder as it is the 'gen' folder.
+                        if (sourceFolderPath.equals(mSourceFolder.getFullPath())) {
+                            continue;
+                        }
+                        
+                        IFolder sourceFolder = getFolder(sourceFolderPath);
+                        if (sourceFolder != null) {
+                            // go recursively, segment by segment.
+                            // index starts at 2 (0 is project, 1 is 'gen' 
+                            IFile sourceFile = findFile(sourceFolder, segments, 2, aidlFileName);
+                            
+                            if (sourceFile != null) {
+                                // found the source. add it to the list of files to compile
+                                mAidlToCompile.add(new AidlData(sourceFolder, sourceFile));
+                                outputWarning = true;
+                                break;
                             }
                         }
-                    } else {
-                        // check if it's an android generated java file.
-                        IResource aidlSource = ProjectHelper.loadResourceProperty(
-                                file, PreCompilerBuilder.PROPERTY_ANDROID_GENERATED);
-
-                        if (aidlSource != null && aidlSource.exists() &&
-                                aidlSource.getType() == IResource.FILE) {
-                            // it looks like this was a java file created from an aidl file.
-                            // we need to add the aidl file to the list of aidl file to compile
-                            mAidlToCompile.add((IFile)aidlSource);
-                            outputMessage = true;
-                        }
                     }
                 }
-            }
 
-            if (outputMessage) {
-                if (kind == IResourceDelta.REMOVED) {
-                    // We pring an error just so that it's red, but it's just a warning really.
-                    String msg = String.format(Messages.s_Removed_Recreating_s, fileName);
-                    AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
-                } else if (kind == IResourceDelta.CHANGED) {
-                    // the file was modified manually! we can't allow it.
-                    String msg = String.format(Messages.s_Modified_Manually_Recreating_s, fileName);
-                    AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
+                if (outputWarning) {
+                    if (kind == IResourceDelta.REMOVED) {
+                        // We pring an error just so that it's red, but it's just a warning really.
+                        String msg = String.format(Messages.s_Removed_Recreating_s, fileName);
+                        AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
+                    } else if (kind == IResourceDelta.CHANGED) {
+                        // the file was modified manually! we can't allow it.
+                        String msg = String.format(Messages.s_Modified_Manually_Recreating_s,
+                                fileName);
+                        AdtPlugin.printErrorToConsole(mBuilder.getProject(), msg);
+                    }
+                }
+
+            } else {
+                // this is another source folder.
+                // We only care about aidl files being added/modified/removed.
+
+                // get the extension of the resource
+                String ext = resource.getFileExtension();
+                if (AndroidConstants.EXT_AIDL.equalsIgnoreCase(ext)) {
+                    if (kind == IResourceDelta.REMOVED) {
+                        // we'll have to remove the generated file.
+                        mAidlToRemove.add(new AidlData(mSourceFolder, file));
+                    } else {
+                        // add the aidl file to the list of file to (re)compile
+                        mAidlToCompile.add(new AidlData(mSourceFolder, file));
+                    }
                 }
             }
 
@@ -403,19 +364,25 @@
             }
         } else if (resource instanceof IFolder) {
             // in this case we may be inside a folder that contains a source
-            // folder.
-            String[] sourceFolderSegments = findMatchingSourceFolder(mSourceFolders, segments);
-            if (sourceFolderSegments != null) {
-                // we have a match!
-                mInRes = false;
+            // folder, go through the list of known source folders
 
-                // Check if the current folder is actually a source folder
-                if (sourceFolderSegments.length == segments.length) {
-                    mInSrc = true;
+            for (IPath sourceFolderPath : mSourceFolders) {
+                // first check if they match exactly.
+                if (sourceFolderPath.equals(path)) {
+                    // this is a source folder!
+                    mInRes = false;
+                    mSourceFolder = getFolder(sourceFolderPath); // all non null due to test above
+                    mIsGenSourceFolder = path.segmentCount() == 2 &&
+                            path.segment(1).equals(SdkConstants.FD_GEN_SOURCES);
+                    return true;
                 }
                 
-                // and return true to visit the content, no matter what
-                return true;
+                // check if we are on the way to a source folder.
+                int count = sourceFolderPath.matchingFirstSegments(path);
+                if (count == path.segmentCount()) {
+                    mInRes = false;
+                    return true;
+                }
             }
 
             // if we're here, we are visiting another folder
@@ -429,4 +396,46 @@
 
         return false;
     }
+    
+    /**
+     * Searches for and return a file in a folder. The file is defined by its segments, and a new
+     * name (replacing the last segment).
+     * @param folder the folder we are searching
+     * @param segments the segments of the file to search.
+     * @param index the index of the current segment we are looking for
+     * @param filename the new name to replace the last segment.
+     * @return the {@link IFile} representing the searched file, or null if not found
+     */
+    private IFile findFile(IFolder folder, String[] segments, int index, String filename) {
+        boolean lastSegment = index == segments.length - 1;
+        IResource resource = folder.findMember(lastSegment ? filename : segments[index]);
+        if (resource != null && resource.exists()) {
+            if (lastSegment) {
+                if (resource.getType() == IResource.FILE) {
+                    return (IFile)resource;
+                }
+            } else {
+                if (resource.getType() == IResource.FOLDER) {
+                    return findFile((IFolder)resource, segments, index+1, filename);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a handle to the folder identified by the given path in this container.
+     * <p/>The different with {@link IContainer#getFolder(IPath)} is that this returns a non
+     * null object only if the resource actually exists and is a folder (and not a file)
+     * @param path the path of the folder to return.
+     * @return a handle to the folder if it exists, or null otherwise.
+     */
+    private IFolder getFolder(IPath path) {
+        IResource resource = mRoot.findMember(path);
+        if (resource != null && resource.exists() && resource.getType() == IResource.FOLDER) {
+            return (IFolder)resource;
+        }
+        
+        return null;
+    }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
index 19d7185..0255f9f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/build/ResourceManagerBuilder.java
@@ -19,19 +19,27 @@
 import com.android.ide.eclipse.adt.AdtConstants;
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
-import com.android.ide.eclipse.adt.sdk.LoadStatus;
 import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.sdklib.IAndroidTarget;
+import com.android.sdklib.SdkConstants;
 
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
 
+import java.util.ArrayList;
 import java.util.Map;
 
 /**
@@ -56,6 +64,10 @@
 
         // Clear the project of the generic markers
         BaseBuilder.removeMarkersFromProject(project, AdtConstants.MARKER_ADT);
+        
+        // check for existing target marker, in which case we abort.
+        // (this means: no SDK, no target, or unresolvable target.)
+        abortOnBadSetup(project);
 
         // Check the compiler compliance level, displaying the error message
         // since this is the first builder.
@@ -83,8 +95,7 @@
         String osSdkFolder = AdtPlugin.getOsSdkFolder();
 
         if (osSdkFolder == null || osSdkFolder.length() == 0) {
-            AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
-                    Messages.No_SDK_Setup_Error);
+            AdtPlugin.printErrorToConsole(project, Messages.No_SDK_Setup_Error);
             markProject(AdtConstants.MARKER_ADT, Messages.No_SDK_Setup_Error,
                     IMarker.SEVERITY_ERROR);
 
@@ -92,13 +103,6 @@
             stopBuild(Messages.No_SDK_Setup_Error);
         }
 
-        // check if we have finished loading the SDK.
-        if (AdtPlugin.getDefault().getSdkLoadStatus() != LoadStatus.LOADED) {
-            // we exit silently
-            // This interrupts the build. The next builders will not run.
-            stopBuild("SDK is not loaded yet");
-        }
-        
         // check the project has a target
         IAndroidTarget projectTarget = Sdk.getCurrent().getTarget(project);
         if (projectTarget == null) {
@@ -106,6 +110,85 @@
             // This interrupts the build. The next builders will not run.
             stopBuild("Project has no target");
         }
+        
+        // check the 'gen' source folder is present
+        boolean hasGenSrcFolder = false; // whether the project has a 'gen' source folder setup
+        IJavaProject javaProject = JavaCore.create(project);
+        
+        IClasspathEntry[] classpaths = javaProject.readRawClasspath();
+        if (classpaths != null) {
+            for (IClasspathEntry e : classpaths) {
+                if (e.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
+                    IPath path = e.getPath();
+                    if (path.segmentCount() == 2 &&
+                            path.segment(1).equals(SdkConstants.FD_GEN_SOURCES)) {
+                        hasGenSrcFolder = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+        boolean genFolderPresent = false; // whether the gen folder actually exists
+        IResource resource = project.findMember(SdkConstants.FD_GEN_SOURCES);
+        genFolderPresent = resource != null && resource.exists();
+        
+        if (hasGenSrcFolder == false && genFolderPresent) {
+            // No source folder setup for 'gen' in the project, but there's already a
+            // 'gen' resource (file or folder).
+            String message;
+            if (resource.getType() == IResource.FOLDER) {
+                // folder exists already! This is an error. If the folder had been created
+                // by the NewProjectWizard, it'd be a source folder.
+                message = String.format("%1$s already exists but is not a source folder. Convert to a source folder or rename it.",
+                        resource.getFullPath().toString());
+            } else {
+                // resource exists but is not a folder.
+                message = String.format(
+                        "Resource %1$s is in the way. ADT needs a source folder called 'gen' to work. Rename or delete resource.",
+                        resource.getFullPath().toString());
+            }
+
+            AdtPlugin.printErrorToConsole(project, message);
+            markProject(AdtConstants.MARKER_ADT, message, IMarker.SEVERITY_ERROR);
+
+            // This interrupts the build. The next builders will not run.
+            stopBuild(message);
+        } else if (hasGenSrcFolder == false || genFolderPresent == false) {
+            // either there is no 'gen' source folder in the project (older SDK),
+            // or the folder does not exist (was deleted, or was a fresh svn checkout maybe.)
+
+            // In case we are migrating from an older SDK, we go through the current source
+            // folders and delete the generated Java files.
+            ArrayList<IPath> sourceFolders = BaseProjectHelper.getSourceClasspaths(javaProject);
+            IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+            for (IPath path : sourceFolders) {
+                IResource member = root.findMember(path);
+                if (member != null) {
+                    removeDerivedResources(member, monitor);
+                }
+            }
+
+            // create the new source folder, if needed
+            IFolder genFolder = project.getFolder(SdkConstants.FD_GEN_SOURCES);
+            if (genFolderPresent == false) {
+                AdtPlugin.printBuildToConsole(AdtConstants.BUILD_VERBOSE, project,
+                        "Creating 'gen' source folder for generated Java files");
+                genFolder.create(true /* force */, true /* local */,
+                        new SubProgressMonitor(monitor, 10));
+            }
+            
+            // add it to the source folder list, if needed only (or it will throw)
+            if (hasGenSrcFolder == false) {
+                IClasspathEntry[] entries = javaProject.getRawClasspath();
+                entries = ProjectHelper.addEntryToClasspath(entries,
+                        JavaCore.newSourceEntry(genFolder.getFullPath()));
+                javaProject.setRawClasspath(entries, new SubProgressMonitor(monitor, 10));
+            }
+            
+            // refresh the whole project
+            project.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 10));
+        }
 
         // Check the preference to be sure we are supposed to refresh
         // the folders.
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunch.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunch.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java
index 3d60401..7029206 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunch.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunch.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
 
 import org.eclipse.debug.core.DebugException;
 import org.eclipse.debug.core.ILaunchConfiguration;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
similarity index 99%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
index ac003df..9c5f09b 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/AndroidLaunchController.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
 
 import com.android.ddmlib.AndroidDebugBridge;
 import com.android.ddmlib.Client;
@@ -28,8 +28,7 @@
 import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
 import com.android.ddmlib.SyncService.SyncResult;
 import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.DeviceChooserDialog.DeviceChooserResponse;
-import com.android.ide.eclipse.adt.debug.ui.EmulatorConfigTab;
+import com.android.ide.eclipse.adt.launch.DeviceChooserDialog.DeviceChooserResponse;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
 import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.project.AndroidManifestHelper;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java
similarity index 99%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java
index a260350..275addf 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/DeviceChooserDialog.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DeviceChooserDialog.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
 
 import com.android.ddmlib.AndroidDebugBridge;
 import com.android.ddmlib.Client;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java
similarity index 99%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java
index d919c1f..5b4cdbb 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/EmulatorConfigTab.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/EmulatorConfigTab.java
@@ -14,10 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.debug.ui;
+package com.android.ide.eclipse.adt.launch;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
 import com.android.ide.eclipse.adt.sdk.Sdk;
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.ide.eclipse.ddms.DdmsPlugin;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegate.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegate.java
new file mode 100644
index 0000000..7a74309
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegate.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.common.AndroidConstants;
+import com.android.sdklib.SdkConstants;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.jdt.junit.launcher.JUnitLaunchConfigurationDelegate;
+import org.osgi.framework.Bundle;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * <p>
+ * For Android projects, android.jar gets added to the launch configuration of
+ * JUnit tests as a bootstrap entry. This breaks JUnit tests as android.jar
+ * contains a skeleton version of JUnit classes and the JVM will stop with an error similar
+ * to: <blockquote> Error occurred during initialization of VM
+ * java/lang/NoClassDefFoundError: java/lang/ref/FinalReference </blockquote>
+ * <p>
+ * At compile time, Eclipse does not know that there is no valid junit.jar in
+ * the classpath since it can find a correct reference to all the necessary
+ * org.junit.* classes in the android.jar so it does not prompt the user to add
+ * the JUnit3 or JUnit4 jar.
+ * <p>
+ * This delegates removes the android.jar from the bootstrap path and if
+ * necessary also puts back the junit.jar in the user classpath.
+ * <p>
+ * This delegate will be present for both Java and Android projects (delegates
+ * setting instead of only the current project) but the behavior for Java
+ * projects should be neutral since:
+ * <ol>
+ * <li>Java tests can only compile (and then run) when a valid junit.jar is
+ * present
+ * <li>There is no android.jar in Java projects
+ * </ol>
+ */
+public class JUnitLaunchConfigDelegate extends JUnitLaunchConfigurationDelegate {
+
+    private static final String JUNIT_JAR = "junit.jar"; //$NON-NLS-1$
+
+    @Override
+    public String[][] getBootpathExt(ILaunchConfiguration configuration) throws CoreException {
+        String[][] bootpath = super.getBootpathExt(configuration);
+        return fixBootpathExt(bootpath);
+    }
+
+    @Override
+    public String[] getClasspath(ILaunchConfiguration configuration) throws CoreException {
+        String[] classpath = super.getClasspath(configuration);
+        return fixClasspath(classpath, getJavaProjectName(configuration));
+    }
+
+    /**
+     * Removes the android.jar from the bootstrap path if present.
+     * 
+     * @param bootpath Array of Arrays of bootstrap class paths
+     * @return a new modified (if applicable) bootpath
+     */
+    public static String[][] fixBootpathExt(String[][] bootpath) {
+        for (int i = 0; i < bootpath.length; i++) {
+            if (bootpath[i] != null) {
+                // we assume that the android.jar can only be present in the
+                // bootstrap path of android tests
+                if (bootpath[i][0].endsWith(SdkConstants.FN_FRAMEWORK_LIBRARY)) {
+                    bootpath[i] = null;
+                }
+            }
+        }
+        return bootpath;
+    }
+
+    /**
+     * Add the junit.jar to the user classpath; since Eclipse was relying on
+     * android.jar to provide the appropriate org.junit classes, it does not
+     * know it actually needs the junit.jar.
+     * 
+     * @param classpath Array containing classpath 
+     * @param projectName The name of the project (for logging purposes) 
+     * 
+     * @return a new modified (if applicable) classpath
+     */
+    public static String[] fixClasspath(String[] classpath, String projectName) {
+        // search for junit.jar; if any are found return immediately
+        for (int i = 0; i < classpath.length; i++) {
+            if (classpath[i].endsWith(JUNIT_JAR)) { 
+                return classpath;
+            }
+        }
+
+        // This delegate being called without a junit.jar present is only
+        // possible for Android projects. In a non-Android project, the test
+        // would not compile and would be unable to run.
+        try {
+            // junit4 is backward compatible with junit3 and they uses the
+            // same junit.jar from bundle org.junit:
+            // When a project has mixed JUnit3 and JUnit4 tests, if JUnit3 jar
+            // is added first it is then replaced by the JUnit4 jar when user is
+            // prompted to fix the JUnit4 test failure
+            String jarLocation = getJunitJarLocation();
+            // we extend the classpath by one element and append junit.jar
+            String[] newClasspath = new String[classpath.length + 1];
+            System.arraycopy(classpath, 0, newClasspath, 0, classpath.length);
+            newClasspath[newClasspath.length - 1] = jarLocation;
+            classpath = newClasspath;
+        } catch (IOException e) {
+            // This should not happen as we depend on the org.junit
+            // plugin explicitly; the error is logged here so that the user can
+            // trace back the cause when the test fails to run
+            AdtPlugin.log(e, "Could not find a valid junit.jar");
+            AdtPlugin.printErrorToConsole(projectName,
+                    "Could not find a valid junit.jar");
+            // Return the classpath as-is (with no junit.jar) anyway because we
+            // will let the actual launch config fails.
+        }
+
+        return classpath;
+    }
+
+    /**
+     * Returns the path of the junit jar in the highest version bundle.
+     * 
+     * (This is public only so that the test can call it)
+     * 
+     * @return the path as a string
+     * @throws IOException
+     */
+    public static String getJunitJarLocation() throws IOException {
+        Bundle bundle = Platform.getBundle("org.junit"); //$NON-NLS-1$
+        if (bundle == null) {
+            throw new IOException("Cannot find org.junit bundle");
+        }
+        URL jarUrl = bundle.getEntry(AndroidConstants.WS_SEP + JUNIT_JAR);
+        return FileLocator.resolve(jarUrl).getFile();
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
index bbd320b..a46f56c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchConfigDelegate.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
 
 import com.android.ddmlib.AndroidDebugBridge;
 import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController.AndroidLaunchConfiguration;
+import com.android.ide.eclipse.adt.launch.AndroidLaunchController.AndroidLaunchConfiguration;
 import com.android.ide.eclipse.adt.project.ProjectHelper;
 import com.android.ide.eclipse.common.AndroidConstants;
 import com.android.ide.eclipse.common.project.AndroidManifestParser;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/LaunchConfigTabGroup.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigTabGroup.java
similarity index 96%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/LaunchConfigTabGroup.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigTabGroup.java
index c0dbd54..f1dbd26 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/LaunchConfigTabGroup.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigTabGroup.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.debug.ui;
+package com.android.ide.eclipse.adt.launch;
 
 import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
 import org.eclipse.debug.ui.CommonTab;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchShortcut.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchShortcut.java
similarity index 97%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchShortcut.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchShortcut.java
index 92677f1..6b2744c 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/launching/LaunchShortcut.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchShortcut.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.debug.launching;
+package com.android.ide.eclipse.adt.launch;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/MainLaunchConfigTab.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/MainLaunchConfigTab.java
similarity index 98%
rename from tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/MainLaunchConfigTab.java
rename to tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/MainLaunchConfigTab.java
index 6a40ed0..599da5f 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/debug/ui/MainLaunchConfigTab.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/MainLaunchConfigTab.java
@@ -14,11 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.ide.eclipse.adt.debug.ui;
+package com.android.ide.eclipse.adt.launch;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.AndroidLaunchController;
-import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
 import com.android.ide.eclipse.common.project.AndroidManifestParser;
 import com.android.ide.eclipse.common.project.BaseProjectHelper;
 import com.android.ide.eclipse.common.project.ProjectChooserHelper;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
deleted file mode 100644
index a1b3c38..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/CreateAidlImportAction.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Eclipse Public License, Version 1.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.eclipse.org/org/documents/epl-v10.php
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ide.eclipse.adt.project;
-
-import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.common.AndroidConstants;
-
-import org.eclipse.core.resources.IProject;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IJavaElement;
-import org.eclipse.jdt.core.IJavaProject;
-import org.eclipse.jdt.core.IPackageFragment;
-import org.eclipse.jdt.core.IPackageFragmentRoot;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.ITypeHierarchy;
-import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jface.action.IAction;
-import org.eclipse.jface.viewers.ISelection;
-import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.ui.IObjectActionDelegate;
-import org.eclipse.ui.IWorkbenchPart;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * Action going through all the source of a project and creating a pre-processed aidl file
- * with all the custom parcelable classes.
- */
-public class CreateAidlImportAction  implements IObjectActionDelegate {
-
-    private ISelection mSelection;
-
-    public CreateAidlImportAction() {
-        // pass
-    }
-
-    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
-        // pass
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
-     */
-    public void run(IAction action) {
-        if (mSelection instanceof IStructuredSelection) {
-            for (Iterator<?> it = ((IStructuredSelection)mSelection).iterator(); it.hasNext();) {
-                Object element = it.next();
-                IProject project = null;
-                if (element instanceof IProject) {
-                    project = (IProject)element;
-                } else if (element instanceof IAdaptable) {
-                    project = (IProject)((IAdaptable)element).getAdapter(IProject.class);
-                }
-                if (project != null) {
-                    final IProject fproject = project;
-                    new Job("Aidl preprocess") {
-                        @Override
-                        protected IStatus run(IProgressMonitor monitor) {
-                            return createImportFile(fproject, monitor);
-                        }
-                    }.schedule();
-                }
-            }
-        }
-    }
-
-    public void selectionChanged(IAction action, ISelection selection) {
-        mSelection = selection;
-    }
-
-    private IStatus createImportFile(IProject project, IProgressMonitor monitor) {
-        try {
-            if (monitor != null) {
-                monitor.beginTask(String.format(
-                        "Creating aid preprocess file for %1$s", project.getName()), 1);
-            }
-            
-            ArrayList<String> parcelables = new ArrayList<String>();
-            
-            IJavaProject javaProject = JavaCore.create(project);
-            
-            IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
-            
-            for (IPackageFragmentRoot root : roots) {
-                if (root.isArchive() == false && root.isExternal() == false) {
-                    parsePackageFragmentRoot(root, parcelables, monitor);
-                }
-            }
-            
-            // create the file with the parcelables
-            if (parcelables.size() > 0) {
-                IPath path = project.getLocation();
-                path = path.append(AndroidConstants.FN_PROJECT_AIDL);
-                
-                File f = new File(path.toOSString());
-                if (f.exists() == false) {
-                    if (f.createNewFile() == false) {
-                        return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
-                                "Failed to create /project.aidl");
-                    }
-                }
-                
-                FileWriter fw = new FileWriter(f);
-                
-                fw.write("// This file is auto-generated by the\n");
-                fw.write("//    'Create Aidl preprocess file for Parcelable classes'\n");
-                fw.write("// action. Do not modify!\n\n");
-                
-                for (String parcelable : parcelables) {
-                    fw.write("parcelable "); //$NON-NLS-1$
-                    fw.write(parcelable);
-                    fw.append(";\n"); //$NON-NLS-1$
-                }
-                
-                fw.close();
-                
-                // need to refresh the level just below the project to make sure it's being picked
-                // up by eclipse.
-                project.refreshLocal(IResource.DEPTH_ONE, monitor);
-            }
-            
-            if (monitor != null) {
-                monitor.worked(1);
-                monitor.done();
-            }
-            
-            return Status.OK_STATUS;
-        } catch (JavaModelException e) {
-            return e.getJavaModelStatus();
-        } catch (IOException e) {
-            return new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
-                    "Failed to create /project.aidl", e);
-        } catch (CoreException e) {
-            return e.getStatus();
-        } finally {
-            if (monitor != null) {
-                monitor.done();
-            }
-        }
-    }
-    
-    private void parsePackageFragmentRoot(IPackageFragmentRoot root,
-            ArrayList<String> parcelables, IProgressMonitor monitor) throws JavaModelException {
-        
-        IJavaElement[] elements = root.getChildren();
-        
-        for (IJavaElement element : elements) {
-            if (element instanceof IPackageFragment) {
-                ICompilationUnit[] compilationUnits =
-                    ((IPackageFragment)element).getCompilationUnits();
-                
-                for (ICompilationUnit unit : compilationUnits) {
-                    IType[] types = unit.getTypes();
-                    
-                    for (IType type : types) {
-                        parseType(type, parcelables, monitor);
-                    }
-                }
-            }
-        }
-    }
-
-    private void parseType(IType type, ArrayList<String> parcelables, IProgressMonitor monitor)
-            throws JavaModelException {
-        // first look in this type if it somehow extends parcelable.
-        ITypeHierarchy typeHierarchy = type.newSupertypeHierarchy(monitor);
-        
-        IType[] superInterfaces = typeHierarchy.getAllSuperInterfaces(type);
-        for (IType superInterface : superInterfaces) {
-            if (AndroidConstants.CLASS_PARCELABLE.equals(superInterface.getFullyQualifiedName())) {
-                parcelables.add(type.getFullyQualifiedName());
-            }
-        }
-        
-        // then look in inner types.
-        IType[] innerTypes = type.getTypes();
-        
-        for (IType innerType : innerTypes) {
-            parseType(innerType, parcelables, monitor);
-        }
-    }
-}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java
index b8a0b0c..49bbd81 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FixLaunchConfig.java
@@ -17,7 +17,7 @@
 package com.android.ide.eclipse.adt.project;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
-import com.android.ide.eclipse.adt.debug.launching.LaunchConfigDelegate;
+import com.android.ide.eclipse.adt.launch.LaunchConfigDelegate;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.runtime.CoreException;
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
index 7fc3318..59b2b06 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/project/FolderDecorator.java
@@ -39,7 +39,7 @@
     private ImageDescriptor mDescriptor;
 
     public FolderDecorator() {
-        mDescriptor = AdtPlugin.getImageDescriptor("/icons/android_project.png");
+        mDescriptor = AdtPlugin.getImageDescriptor("/icons/android_project.png"); //$NON-NLS-1$
     }
 
     public void decorate(Object element, IDecoration decoration) {
@@ -55,13 +55,13 @@
                     if (folder.getParent().getType() == IResource.PROJECT) {
                         String name = folder.getName();
                         if (name.equals(SdkConstants.FD_ASSETS)) {
-                            decorate(decoration, " [Android assets]");
-                            decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+                            doDecoration(decoration, null);
                         } else if (name.equals(SdkConstants.FD_RESOURCES)) {
-                            decorate(decoration, " [Android resources]");
-                            decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
-                        } else if (name.equals(SdkConstants.FD_NATIVE_LIBS)) {
-                            decorate(decoration, " [Native Libraries]");
+                            doDecoration(decoration, null);
+                        } else if (name.equals(SdkConstants.FD_GEN_SOURCES)) {
+                            doDecoration(decoration, " [Generated Java Files]");
+                      } else if (name.equals(SdkConstants.FD_NATIVE_LIBS)) {
+                          doDecoration(decoration, null);
                         }
                     }
                 }
@@ -72,20 +72,24 @@
         }
     }
     
-    public void decorate(IDecoration decoration, String suffix) {
-        decoration.addOverlay(mDescriptor, IDecoration.TOP_RIGHT);
+    public void doDecoration(IDecoration decoration, String suffix) {
+        decoration.addOverlay(mDescriptor, IDecoration.TOP_LEFT);
 
-        // this is broken as it changes the color of the whole text, not only of the decoration.
-        // TODO: figure out how to change the color of the decoration only.
-//        decoration.addSuffix(suffix);
-//        ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
-//        ColorRegistry registry = theme.getColorRegistry();
-//        decoration.setForegroundColor(registry.get("org.eclipse.jdt.ui.ColoredLabels.decorations"));
+        if (suffix != null) {
+            decoration.addSuffix(suffix);
+
+            // this is broken as it changes the color of the whole text, not only of the decoration.
+            // TODO: figure out how to change the color of the decoration only.
+//            ITheme theme = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme();
+//            ColorRegistry registry = theme.getColorRegistry();
+//            decoration.setForegroundColor(
+//                    registry.get("org.eclipse.jdt.ui.ColoredLabels.decorations")); //$NON-NLS-1$
+        }
 
     }
 
     public boolean isLabelProperty(Object element, String property) {
-        // at this time return false.
+        // Property change do not affect the label
         return false;
     }
 
@@ -93,13 +97,11 @@
         // No state change will affect the rendering.
     }
 
-
-
     public void removeListener(ILabelProviderListener listener) {
         // No state change will affect the rendering.
     }
 
     public void dispose() {
-        // nothind to dispose
+        // nothing to dispose
     }
 }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
index e201132..5abfd81 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/AndroidConstants.java
@@ -87,7 +87,6 @@
 
     /** Name of the manifest file, i.e. "AndroidManifest.xml". */
     public static final String FN_ANDROID_MANIFEST = "AndroidManifest.xml"; //$NON-NLS-1$
-    public static final String FN_PROJECT_AIDL = "project.aidl"; //$NON-NLS-1$
 
     /** Name of the android sources directory */
     public static final String FD_ANDROID_SOURCES = "sources"; //$NON-NLS-1$
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF b/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
index 266008c..c7f5ba8 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/META-INF/MANIFEST.MF
@@ -13,7 +13,7 @@
  org.eclipse.jdt.launching,
  org.eclipse.ui.views,
  com.android.ide.eclipse.ddms
-Eclipse-LazyStart: true
+Bundle-ActivationPolicy: lazy
 Bundle-Vendor: The Android Open Source Project
 Bundle-ClassPath: kxml2-2.3.0.jar,
  .
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegateTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegateTest.java
new file mode 100644
index 0000000..df3745e
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/launch/JUnitLaunchConfigDelegateTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.ide.eclipse.adt.launch;
+
+import java.io.IOException;
+import java.util.Arrays;
+import junit.framework.TestCase;
+
+public class JUnitLaunchConfigDelegateTest extends TestCase {
+
+    public void testAbleToFetchJunitJar() throws IOException {
+        assertTrue(JUnitLaunchConfigDelegate.getJunitJarLocation().endsWith("junit.jar"));
+    }
+    
+    public void testFixBootpathExtWithAndroidJar() {
+        String[][] testArray = {
+                null,
+                { "android.jar"},
+                null,
+                { "some_other_jar.jar" },
+        };
+        
+        String[][] expectedArray = {
+                null,
+                null,
+                null,
+                { "some_other_jar.jar" },
+        };
+        
+       assertEqualsArrays(expectedArray, JUnitLaunchConfigDelegate.fixBootpathExt(testArray));
+    }
+
+    public void testFixBootpathExtWithNoAndroidJar() {
+        String[][] testArray = {
+                null,
+                { "somejar.jar"},
+                null,
+        };
+        
+        String[][] expectedArray = {
+                null,
+                { "somejar.jar"},
+                null,
+        };
+        
+        assertEqualsArrays(expectedArray, JUnitLaunchConfigDelegate.fixBootpathExt(testArray));
+    }
+
+    public void testFixClasspathWithJunitJar() throws IOException {
+        String[] testArray = {
+                JUnitLaunchConfigDelegate.getJunitJarLocation(),
+        };
+        
+        String[] expectedArray = {
+                JUnitLaunchConfigDelegate.getJunitJarLocation(),
+        };
+        
+        assertEqualsArrays(expectedArray, 
+                JUnitLaunchConfigDelegate.fixClasspath(testArray, "test"));
+    }
+    
+    public void testFixClasspathWithoutJunitJar() throws IOException {
+        String[] testArray = {
+                "random.jar",
+        };
+        
+        String[] expectedArray = {
+                "random.jar",
+                JUnitLaunchConfigDelegate.getJunitJarLocation(),
+        };
+        
+        assertEqualsArrays(expectedArray, 
+                JUnitLaunchConfigDelegate.fixClasspath(testArray, "test"));
+    }
+
+
+    public void testFixClasspathWithNoJars() throws IOException {
+        String[] testArray = {
+        };
+        
+        String[] expectedArray = {
+                JUnitLaunchConfigDelegate.getJunitJarLocation(),
+        };
+        
+        assertEqualsArrays(expectedArray, 
+                JUnitLaunchConfigDelegate.fixClasspath(testArray, "test"));
+    }
+
+    private void assertEqualsArrays(String[][] a1, String[][] a2) {
+        assertTrue(Arrays.deepEquals(a1, a2));        
+    }
+    
+    private void assertEqualsArrays(String[] a1, String[] a2) {
+        assertTrue(Arrays.deepEquals(a1, a2));        
+    }
+}
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java
index 29538bb..6aaa209 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/EclipseTestCollector.java
@@ -15,15 +15,14 @@
  */
 package com.android.ide.eclipse.tests;
 
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
 import org.eclipse.core.runtime.Plugin;
 
 import java.lang.reflect.Modifier;
 import java.net.URL;
 import java.util.Enumeration;
-import java.util.logging.Logger;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
 
 /**
  * Class for collecting all test cases in an eclipse plugin
@@ -31,8 +30,6 @@
  */
 public class EclipseTestCollector {
 
-    private static final Logger sLogger = Logger.getLogger(EclipseTestCollector.class.getName());
-    
     /**
      * Constructor
      */
@@ -49,13 +46,13 @@
      */
     public void addTestCases(TestSuite suite, Plugin plugin, String expectedPackage) {
         if (plugin != null) {
-            Enumeration entries = plugin.getBundle().findEntries("/", "*.class", true);
+            Enumeration<?> entries = plugin.getBundle().findEntries("/", "*.class", true);
     
             while (entries.hasMoreElements()) {
                 URL entry = (URL)entries.nextElement();
                 String filePath = entry.getPath().replace(".class", "");
                 try {
-                  Class testClass = getClass(filePath, expectedPackage);
+                  Class<?> testClass = getClass(filePath, expectedPackage);
                   if (isTestClass(testClass)) {
                       suite.addTestSuite(testClass);
                   }
@@ -69,11 +66,11 @@
     }
     
     /**
-     * Returns true if given class shouk\ld be added to suite
+     * Returns true if given class should be added to suite
      * @param testClass
      * @return
      */
-    protected boolean isTestClass(Class testClass) {
+    protected boolean isTestClass(Class<?> testClass) {
         return TestCase.class.isAssignableFrom(testClass) &&
           Modifier.isPublic(testClass.getModifiers()) &&
           hasPublicConstructor(testClass);
@@ -84,7 +81,7 @@
      * @param testClass
      * @return
      */
-    protected boolean hasPublicConstructor(Class testClass) {
+    protected boolean hasPublicConstructor(Class<?> testClass) {
         try {
             TestSuite.getTestConstructor(testClass);
         } catch(NoSuchMethodException e) {
@@ -100,7 +97,7 @@
      * @return
      * @throws ClassNotFoundException
      */
-    protected Class getClass(String filePath, String expectedPackage) throws ClassNotFoundException {
+    protected Class<?> getClass(String filePath, String expectedPackage) throws ClassNotFoundException {
         String dotPath = filePath.replace('/', '.');
         // remove the output folders, by finding where package name starts
         int index = dotPath.indexOf(expectedPackage);
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
index ac928db..67e7cb2 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/tests/UnitTests.java
@@ -49,7 +49,7 @@
          * Override parent class to exclude functional tests
          */
         @Override
-        protected boolean isTestClass(Class testClass) {
+        protected boolean isTestClass(Class<?> testClass) {
             return super.isTestClass(testClass) &&
             !testClass.getPackage().getName().startsWith(FuncTests.FUNC_TEST_PACKAGE);
         }
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java
index 25a86c3..46e60ba 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/ConfigMatchTest.java
@@ -31,7 +31,6 @@
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
-import java.util.ArrayList;
 
 import junit.framework.TestCase;
 
@@ -47,7 +46,6 @@
     private FolderConfiguration config2;
     private FolderConfiguration config1;
 
-    @SuppressWarnings("unchecked")
     @Override
     protected void setUp() throws Exception {
         super.setUp();
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java
index 6a555a4..0920f00 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/editors/resources/manager/QualifierListTest.java
@@ -20,7 +20,6 @@
 import com.android.ide.eclipse.editors.resources.configurations.ResourceQualifier;
 
 import java.lang.reflect.Field;
-import java.util.ArrayList;
 
 import junit.framework.TestCase;
 
@@ -41,7 +40,6 @@
         mManager = null;
     }
     
-    @SuppressWarnings("unchecked")
     public void testQualifierList() {
         try {
             // get the list of qualifier in the resource manager
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java
index a95286c..2220ed1 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FileMock.java
@@ -424,11 +424,13 @@
         throw new NotImplementedException();
     }
 
-	public Map getPersistentProperties() throws CoreException {
+	@SuppressWarnings("unchecked")
+    public Map getPersistentProperties() throws CoreException {
         throw new NotImplementedException();
 	}
 
-	public Map getSessionProperties() throws CoreException {
+	@SuppressWarnings("unchecked")
+    public Map getSessionProperties() throws CoreException {
         throw new NotImplementedException();
 	}
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java
index 223deb0..73a69aa 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/FolderMock.java
@@ -428,11 +428,11 @@
         throw new NotImplementedException();
     }
 
-	public Map getPersistentProperties() throws CoreException {
+	public Map<?,?> getPersistentProperties() throws CoreException {
         throw new NotImplementedException();
 	}
 
-	public Map getSessionProperties() throws CoreException {
+	public Map<?,?> getSessionProperties() throws CoreException {
         throw new NotImplementedException();
 	}
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java
index 4c409dc..0e6fde0 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/mock/ProjectMock.java
@@ -42,6 +42,7 @@
 import java.net.URI;
 import java.util.Map;
 
+@SuppressWarnings("deprecation")
 public class ProjectMock implements IProject {
 
     public void build(int kind, IProgressMonitor monitor) throws CoreException {
@@ -95,7 +96,6 @@
         throw new NotImplementedException();
     }
 
-    @SuppressWarnings("deprecation")
     public IPath getPluginWorkingLocation(IPluginDescriptor plugin) {
         throw new NotImplementedException();
     }
@@ -459,6 +459,8 @@
         throw new NotImplementedException();
     }
 
+    
+    @SuppressWarnings("unchecked")
     public Object getAdapter(Class adapter) {
         throw new NotImplementedException();
     }
@@ -476,11 +478,11 @@
         throw new NotImplementedException();
 	}
 
-	public Map getPersistentProperties() throws CoreException {
+	public Map<?,?> getPersistentProperties() throws CoreException {
         throw new NotImplementedException();
 	}
 
-	public Map getSessionProperties() throws CoreException {
+	public Map<?,?> getSessionProperties() throws CoreException {
         throw new NotImplementedException();
 	}
 
diff --git a/tools/ninepatch/src/com/android/ninepatch/NinePatch.java b/tools/ninepatch/src/com/android/ninepatch/NinePatch.java
index 39e05c6..35a1824 100644
--- a/tools/ninepatch/src/com/android/ninepatch/NinePatch.java
+++ b/tools/ninepatch/src/com/android/ninepatch/NinePatch.java
@@ -127,8 +127,7 @@
         
 
         try {
-            if (mPatches.size() == 0 || mHorizontalPatches.size() == 0 ||
-                    mVerticalPatches.size() == 0) {
+            if (mPatches.size() == 0) {
                 g.drawImage(mImage, x, y, scaledWidth, scaledHeight, null);
                 return;
             }
@@ -254,6 +253,14 @@
                     start = rect.x;
                 }
             }
+        } else {
+            int start = -1;
+            for (Rectangle rect : mPatches) {
+                if (rect.x > start) {
+                    mHorizontalPatchesSum += rect.width;
+                    start = rect.x;
+                }
+            }
         }
 
         mVerticalPatchesSum = 0;
@@ -265,6 +272,14 @@
                     start = rect.y;
                 }
             }
+        } else {
+            int start = -1;
+            for (Rectangle rect : mPatches) {
+                if (rect.y > start) {
+                    mVerticalPatchesSum += rect.height;
+                    start = rect.y;
+                }
+            }
         }
     }
 
@@ -286,28 +301,11 @@
         boolean[] result = new boolean[1];
         Pair<List<Pair<Integer>>> left = getPatches(column, result);
         mVerticalStartWithPatch = result[0];
-        
-        // compute the min size, based on the list of fixed sections, which is stored in 
-        // Pair.mFirst
-        mMinHeight = 0;
-        List<Pair<Integer>> fixedSections = left.mFirst;
-        for (Pair<Integer> section : fixedSections) {
-            mMinHeight += section.mSecond - section.mFirst;
-        }
 
         result = new boolean[1];
         Pair<List<Pair<Integer>>> top = getPatches(row, result);
         mHorizontalStartWithPatch = result[0];
 
-        // compute the min size, based on the list of fixed sections, which is stored in 
-        // Pair.mFirst
-
-        mMinWidth = 0;
-        fixedSections = top.mFirst;
-        for (Pair<Integer> section : fixedSections) {
-            mMinWidth += section.mSecond - section.mFirst;
-        }
-
         mFixed = getRectangles(left.mFirst, top.mFirst);
         mPatches = getRectangles(left.mSecond, top.mSecond);
 
@@ -315,7 +313,15 @@
             mHorizontalPatches = getRectangles(left.mFirst, top.mSecond);
             mVerticalPatches = getRectangles(left.mSecond, top.mFirst);
         } else {
-            mHorizontalPatches = mVerticalPatches = new ArrayList<Rectangle>(0);
+            if (top.mFirst.size() > 0) {
+                mHorizontalPatches = new ArrayList<Rectangle>(0);
+                mVerticalPatches = getVerticalRectangles(top.mFirst);
+            } else if (left.mFirst.size() > 0) {
+                mHorizontalPatches = getHorizontalRectangles(left.mFirst);
+                mVerticalPatches = new ArrayList<Rectangle>(0);
+            } else {
+                mHorizontalPatches = mVerticalPatches = new ArrayList<Rectangle>(0);
+            }
         }
 
         row = GraphicsUtilities.getPixels(mImage, 0, height - 1, width, 1, row);
@@ -326,31 +332,30 @@
 
         left = getPatches(column, result);
         mVerticalPadding = getPadding(left.mFirst);
-        
-        mHorizontalPatchesSum = 0;
-        if (mHorizontalPatches.size() > 0) {
-            int start = -1;
-            for (Rectangle rect : mHorizontalPatches) {
-                if (rect.x > start) {
-                    mHorizontalPatchesSum += rect.width;
-                    start = rect.x;
-                }
-            }
-        }
-
-        mVerticalPatchesSum = 0;
-        if (mVerticalPatches.size() > 0) {
-            int start = -1;
-            for (Rectangle rect : mVerticalPatches) {
-                if (rect.y > start) {
-                    mVerticalPatchesSum += rect.height;
-                    start = rect.y;
-                }
-            }
-        }
-
     }
-    
+
+    private List<Rectangle> getVerticalRectangles(List<Pair<Integer>> topPairs) {
+        List<Rectangle> rectangles = new ArrayList<Rectangle>();
+        for (Pair<Integer> top : topPairs) {
+            int x = top.mFirst;
+            int width = top.mSecond - top.mFirst;
+
+            rectangles.add(new Rectangle(x, 1, width, mImage.getHeight() - 2));
+        }
+        return rectangles;
+    }
+
+    private List<Rectangle> getHorizontalRectangles(List<Pair<Integer>> leftPairs) {
+        List<Rectangle> rectangles = new ArrayList<Rectangle>();
+        for (Pair<Integer> left : leftPairs) {
+            int y = left.mFirst;
+            int height = left.mSecond - left.mFirst;
+
+            rectangles.add(new Rectangle(1, y, mImage.getWidth() - 2, height));
+        }
+        return rectangles;
+    }
+
     private Pair<Integer> getPadding(List<Pair<Integer>> pairs) {
         if (pairs.size() == 0) {
             return new Pair<Integer>(0, 0);
@@ -366,14 +371,14 @@
                     pairs.get(index).mSecond - pairs.get(index).mFirst);
         }
     }
-    
+
     private List<Rectangle> getRectangles(List<Pair<Integer>> leftPairs,
             List<Pair<Integer>> topPairs) {
         List<Rectangle> rectangles = new ArrayList<Rectangle>();
         for (Pair<Integer> left : leftPairs) {
             int y = left.mFirst;
             int height = left.mSecond - left.mFirst;
-            for (Pair<Integer> top: topPairs) {
+            for (Pair<Integer> top : topPairs) {
                 int x = top.mFirst;
                 int width = top.mSecond - top.mFirst;
 
@@ -382,7 +387,7 @@
         }
         return rectangles;
     }
-    
+
     private Pair<List<Pair<Integer>>> getPatches(int[] pixels, boolean[] startWithPatch) {
         int lastIndex = 1;
         int lastPixel = pixels[1];
@@ -390,7 +395,7 @@
 
         List<Pair<Integer>> fixed = new ArrayList<Pair<Integer>>();
         List<Pair<Integer>> patches = new ArrayList<Pair<Integer>>();
-        
+
         for (int i = 1; i < pixels.length - 1; i++) {
             int pixel = pixels[i];
             if (pixel != lastPixel) {
@@ -418,6 +423,7 @@
             startWithPatch[0] = true;
             fixed.clear();
         }
+
         return new Pair<List<Pair<Integer>>>(fixed, patches);
     }