Merge "Don't copy the whole SdkController into the SDK."
diff --git a/build/tools.atree b/build/tools.atree
index a773941..8fc262c 100644
--- a/build/tools.atree
+++ b/build/tools.atree
@@ -65,7 +65,8 @@
 
 # sdk.git Ant templates for project build files
 sdk/templates/build.template        tools/lib/build.template
-sdk/files/proguard.cfg              tools/lib/proguard.cfg
+sdk/files/proguard-project.txt      tools/lib/proguard-project.txt
+sdk/files/proguard-android.txt      tools/proguard/proguard-android.txt
 
 # Ant Build Rules
 sdk/files/ant                       tools/ant
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
index 2584933..f6fe09f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java
@@ -20,7 +20,9 @@
 import com.android.ide.common.log.ILogger;
 import com.android.ide.common.resources.ResourceFile;
 import com.android.ide.common.sdk.LoadStatus;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler.Solution;
 import com.android.ide.eclipse.adt.internal.VersionCheck;
+import com.android.ide.eclipse.adt.internal.actions.SdkManagerAction;
 import com.android.ide.eclipse.adt.internal.editors.AndroidXmlEditor;
 import com.android.ide.eclipse.adt.internal.editors.IconFactory;
 import com.android.ide.eclipse.adt.internal.editors.common.CommonXmlEditor;
@@ -42,6 +44,7 @@
 import com.android.sdklib.IAndroidTarget;
 import com.android.sdklib.SdkConstants;
 
+import org.eclipse.core.commands.Command;
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IMarkerDelta;
 import org.eclipse.core.resources.IProject;
@@ -59,8 +62,10 @@
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.ui.JavaUI;
+import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceDialog;
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.jface.text.IRegion;
 import org.eclipse.jface.util.IPropertyChangeListener;
@@ -78,11 +83,14 @@
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.browser.IWebBrowser;
 import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
+import org.eclipse.ui.commands.ICommandService;
 import org.eclipse.ui.console.ConsolePlugin;
 import org.eclipse.ui.console.IConsole;
 import org.eclipse.ui.console.IConsoleConstants;
 import org.eclipse.ui.console.MessageConsole;
 import org.eclipse.ui.console.MessageConsoleStream;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+import org.eclipse.ui.handlers.IHandlerService;
 import org.eclipse.ui.ide.IDE;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 import org.eclipse.ui.texteditor.AbstractTextEditor;
@@ -162,15 +170,23 @@
      * checkSdkLocationAndId.
      */
     public static abstract class CheckSdkErrorHandler {
+
+        public enum Solution {
+            NONE,
+            OPEN_SDK_MANAGER,
+            OPEN_ANDROID_PREFS,
+            OPEN_P2_UPDATE
+        }
+
         /** Handle an error message during sdk location check. Returns whatever
          * checkSdkLocationAndId() should returns.
          */
-        public abstract boolean handleError(String message);
+        public abstract boolean handleError(Solution solution, String message);
 
         /** Handle a warning message during sdk location check. Returns whatever
          * checkSdkLocationAndId() should returns.
          */
-        public abstract boolean handleWarning(String message);
+        public abstract boolean handleWarning(Solution solution, String message);
     }
 
     /**
@@ -1064,17 +1080,133 @@
         }
 
         return checkSdkLocationAndId(sdkLocation, new CheckSdkErrorHandler() {
+            private String mTitle = "Android SDK Verification";
             @Override
-            public boolean handleError(String message) {
-                AdtPlugin.displayError("Android SDK Verification", message);
+            public boolean handleError(Solution solution, String message) {
+                displayMessage(solution, message, MessageDialog.ERROR);
                 return false;
             }
 
             @Override
-            public boolean handleWarning(String message) {
-                AdtPlugin.displayWarning("Android SDK Verification", message);
+            public boolean handleWarning(Solution solution, String message) {
+                displayMessage(solution, message, MessageDialog.WARNING);
                 return true;
             }
+
+            private void displayMessage(
+                    final Solution solution,
+                    final String message,
+                    final int dialogImageType) {
+                final Display disp = getDisplay();
+                disp.asyncExec(new Runnable() {
+                    @Override
+                    public void run() {
+                        Shell shell = disp.getActiveShell();
+                        if (shell == null) {
+                            return;
+                        }
+
+                        String customLabel = null;
+                        switch(solution) {
+                        case OPEN_ANDROID_PREFS:
+                            customLabel = "Open Preferences";
+                            break;
+                        case OPEN_P2_UPDATE:
+                            customLabel = "Check for Updates";
+                            break;
+                        case OPEN_SDK_MANAGER:
+                            customLabel = "Open SDK Manager";
+                            break;
+                        }
+
+                        String btnLabels[] = new String[customLabel == null ? 1 : 2];
+                        btnLabels[0] = customLabel;
+                        btnLabels[btnLabels.length - 1] = IDialogConstants.CLOSE_LABEL;
+
+                        MessageDialog dialog = new MessageDialog(
+                                shell, // parent
+                                mTitle,
+                                null, // dialogTitleImage
+                                message,
+                                dialogImageType,
+                                btnLabels,
+                                btnLabels.length - 1);
+                        int index = dialog.open();
+
+                        if (customLabel != null && index == 0) {
+                            switch(solution) {
+                            case OPEN_ANDROID_PREFS:
+                                openAndroidPrefs();
+                                break;
+                            case OPEN_P2_UPDATE:
+                                openP2Update();
+                                break;
+                            case OPEN_SDK_MANAGER:
+                                openSdkManager();
+                                break;
+                            }
+                        }
+                    }
+                });
+            }
+
+            private void openSdkManager() {
+                // Windows only: open the standalone external SDK Manager since we know
+                // that ADT on Windows is bound to be locking some SDK folders.
+                if (SdkConstants.CURRENT_PLATFORM == SdkConstants.PLATFORM_WINDOWS) {
+                    if (SdkManagerAction.openExternalSdkManager()) {
+                        return;
+                    }
+                }
+
+                // Otherwise open the regular SDK Manager bundled within ADT
+                if (!SdkManagerAction.openAdtSdkManager()) {
+                    // We failed because the SDK location is undefined. In this case
+                    // let's open the preferences instead.
+                    openAndroidPrefs();
+                }
+            }
+
+            private void openP2Update() {
+                Display disp = getDisplay();
+                if (disp == null) {
+                    return;
+                }
+                disp.asyncExec(new Runnable() {
+                    @Override
+                    public void run() {
+                        String cmdId = "org.eclipse.equinox.p2.ui.sdk.update";  //$NON-NLS-1$
+                        IWorkbench wb = PlatformUI.getWorkbench();
+                        if (wb == null) {
+                            return;
+                        }
+
+                        ICommandService cs = (ICommandService) wb.getService(ICommandService.class);
+                        IHandlerService is = (IHandlerService) wb.getService(IHandlerService.class);
+                        if (cs == null || is == null) {
+                            return;
+                        }
+
+                        Command cmd = cs.getCommand(cmdId);
+                        if (cmd != null && cmd.isDefined()) {
+                            try {
+                                is.executeCommand(cmdId, null/*event*/);
+                            } catch (Exception ignore) {
+                                AdtPlugin.log(ignore, "Failed to execute command %s", cmdId);
+                            }
+                        }
+                    }
+                });
+            }
+
+            private void openAndroidPrefs() {
+                PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(
+                        getDisplay().getActiveShell(),
+                        "com.android.ide.eclipse.preferences.main", //$NON-NLS-1$ preferencePageId
+                        null,  // displayedIds
+                        null); // data
+                dialog.open();
+            }
         });
     }
 
@@ -1093,6 +1225,7 @@
         File osSdkFolder = new File(osSdkLocation);
         if (osSdkFolder.isDirectory() == false) {
             return errorHandler.handleError(
+                    Solution.OPEN_ANDROID_PREFS,
                     String.format(Messages.Could_Not_Find_Folder, osSdkLocation));
         }
 
@@ -1100,6 +1233,7 @@
         File toolsFolder = new File(osTools);
         if (toolsFolder.isDirectory() == false) {
             return errorHandler.handleError(
+                    Solution.OPEN_ANDROID_PREFS,
                     String.format(Messages.Could_Not_Find_Folder_In_SDK,
                             SdkConstants.FD_TOOLS, osSdkLocation));
         }
@@ -1113,13 +1247,17 @@
         // check that we have both the tools component and the platform-tools component.
         String platformTools = osSdkLocation + SdkConstants.OS_SDK_PLATFORM_TOOLS_FOLDER;
         if (checkFolder(platformTools) == false) {
-            return errorHandler.handleWarning("SDK Platform Tools component is missing!\n" +
+            return errorHandler.handleWarning(
+                    Solution.OPEN_SDK_MANAGER,
+                    "SDK Platform Tools component is missing!\n" +
                     "Please use the SDK Manager to install it.");
         }
 
         String tools = osSdkLocation + SdkConstants.OS_SDK_TOOLS_FOLDER;
         if (checkFolder(tools) == false) {
-            return errorHandler.handleError("SDK Tools component is missing!\n" +
+            return errorHandler.handleError(
+                    Solution.OPEN_SDK_MANAGER,
+                    "SDK Tools component is missing!\n" +
                     "Please use the SDK Manager to install it.");
         }
 
@@ -1131,7 +1269,9 @@
         };
         for (String file : filesToCheck) {
             if (checkFile(file) == false) {
-                return errorHandler.handleError(String.format(Messages.Could_Not_Find, file));
+                return errorHandler.handleError(
+                        Solution.OPEN_ANDROID_PREFS,
+                        String.format(Messages.Could_Not_Find, file));
             }
         }
 
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
index 9055b29..b468c5e 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
@@ -18,6 +18,7 @@
 
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler.Solution;
 import com.android.ide.eclipse.adt.Messages;
 import com.android.sdklib.SdkConstants;
 import com.android.sdklib.repository.PkgProps;
@@ -103,7 +104,9 @@
 
         // Failed to get the min plugin version number?
         if (minMajorVersion == -1 || minMinorVersion == -1 || minMicroVersion ==-1) {
-            return errorHandler.handleWarning(Messages.VersionCheck_Plugin_Version_Failed);
+            return errorHandler.handleWarning(
+                    Solution.OPEN_SDK_MANAGER,
+                    Messages.VersionCheck_Plugin_Version_Failed);
         }
 
         // test the plugin number
@@ -126,6 +129,7 @@
 
         if (valid == false) {
             return errorHandler.handleError(
+                    Solution.OPEN_P2_UPDATE,
                     String.format(Messages.VersionCheck_Plugin_Too_Old,
                             minMajorVersion, minMinorVersion, minMicroVersion, versionString));
         }
@@ -163,6 +167,7 @@
             // this is a warning only as we need to parse the SDK to allow updating
             // of the tools!
             return errorHandler.handleWarning(
+                    Solution.OPEN_SDK_MANAGER,
                     String.format(Messages.VersionCheck_Tools_Too_Old,
                             MIN_TOOLS_REV, toolsRevision));
         }
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java
index 970bc47..f8a080a 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/DexDumpAction.java
@@ -22,6 +22,7 @@
 import com.android.sdklib.SdkConstants;
 import com.android.sdklib.util.GrabProcessOutput;
 import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
 
 import org.eclipse.core.filesystem.EFS;
 import org.eclipse.core.filesystem.IFileStore;
@@ -175,7 +176,7 @@
 
                 int err = GrabProcessOutput.grabProcessOutput(
                         process,
-                        true /*waitForReaders*/,
+                        Wait.WAIT_FOR_READERS,
                         new IProcessOutput() {
                             @Override
                             public void out(String line) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java
index ddf180f..0ff50b5 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/actions/SdkManagerAction.java
@@ -20,6 +20,11 @@
 import com.android.ide.eclipse.adt.internal.build.DexWrapper;

 import com.android.ide.eclipse.adt.internal.sdk.AdtConsoleSdkLog;

 import com.android.ide.eclipse.adt.internal.sdk.Sdk;

+import com.android.sdklib.SdkConstants;

+import com.android.sdklib.io.FileOp;

+import com.android.sdklib.util.GrabProcessOutput;

+import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;

+import com.android.sdklib.util.GrabProcessOutput.Wait;

 import com.android.sdkuilib.repository.ISdkChangeListener;

 import com.android.sdkuilib.repository.SdkUpdaterWindow;

 import com.android.sdkuilib.repository.SdkUpdaterWindow.SdkInvocationContext;

@@ -31,6 +36,8 @@
 import org.eclipse.ui.IWorkbenchWindow;

 import org.eclipse.ui.IWorkbenchWindowActionDelegate;

 

+import java.io.File;

+

 /**

  * Delegate for the toolbar/menu action "Android SDK Manager".

  * It displays the Android SDK Manager.

@@ -49,95 +56,163 @@
 

     @Override

     public void run(IAction action) {

-        final Sdk sdk = Sdk.getCurrent();

-        if (sdk != null) {

-

-            // Runs the updater window, directing only warning/errors logs to the ADT console

-            // (normal log is just dropped, which is fine since the SDK Manager has its own

-            // log window now.)

-

-            SdkUpdaterWindow window = new SdkUpdaterWindow(

-                    AdtPlugin.getDisplay().getActiveShell(),

-                    new AdtConsoleSdkLog() {

-                        @Override

-                        public void printf(String msgFormat, Object... args) {

-                            // Do not show non-error/warning log in Eclipse.

-                        };

-                    },

-                    sdk.getSdkLocation(),

-                    SdkInvocationContext.IDE);

-

-            ISdkChangeListener listener = new ISdkChangeListener() {

-                @Override

-                public void onSdkLoaded() {

-                    // Ignore initial load of the SDK.

-                }

-

-                /**

-                 * Unload all we can from the SDK before new packages are installed.

-                 * Typically we need to get rid of references to dx from platform-tools

-                 * and to any platform resource data.

-                 * <p/>

-                 * {@inheritDoc}

-                 */

-                @Override

-                public void preInstallHook() {

-

-                    // TODO we need to unload as much of as SDK as possible. Otherwise

-                    // on Windows we end up with Eclipse locking some files and we can't

-                    // replace them.

-                    //

-                    // At this point, we know what the user wants to install so it would be

-                    // possible to pass in flags to know what needs to be unloaded. Typically

-                    // we need to:

-                    // - unload dex if platform-tools is going to be updated. There's a vague

-                    //   attempt below at removing any references to dex and GCing. Seems

-                    //   to do the trick.

-                    // - unload any target that is going to be updated since it may have

-                    //   resource data used by a current layout editor (e.g. data/*.ttf

-                    //   and various data/res/*.xml).

-                    //

-                    // Most important we need to make sure there isn't a build going on

-                    // and if there is one, either abort it or wait for it to complete and

-                    // then we want to make sure we don't get any attempt to use the SDK

-                    // before the postInstallHook is called.

-

-                    if (sdk != null) {

-                        sdk.unloadTargetData(true /*preventReload*/);

-

-                        DexWrapper dx = sdk.getDexWrapper();

-                        dx.unload();

-                    }

-                }

-

-                /**

-                 * Nothing to do. We'll reparse the SDK later in onSdkReload.

-                 * <p/>

-                 * {@inheritDoc}

-                 */

-                @Override

-                public void postInstallHook() {

-                }

-

-                /**

-                 * Reparse the SDK in case anything was add/removed.

-                 * <p/>

-                 * {@inheritDoc}

-                 */

-                @Override

-                public void onSdkReload() {

-                    AdtPlugin.getDefault().reparseSdk();

-                }

-            };

-

-            window.addListener(listener);

-            window.open();

-        } else {

-            AdtPlugin.displayError("Android SDK",

+        if (!openAdtSdkManager()) {

+            AdtPlugin.displayError(

+                    "Android SDK",

                     "Location of the Android SDK has not been setup in the preferences.");

         }

     }

 

+    /**

+     * Opens the SDK Manager as an external application.

+     * This call is asynchronous, it doesn't wait for the manager to be closed.

+     *

+     * @return True if the application was found and executed. False if it could not

+     *   be located or could not be launched.

+     */

+    public static boolean openExternalSdkManager() {

+        final Sdk sdk = Sdk.getCurrent();

+        if (sdk == null) {

+            return false;

+        }

+

+        File androidBat = FileOp.append(

+                sdk.getSdkLocation(),

+                SdkConstants.FD_TOOLS,

+                SdkConstants.androidCmdName());

+

+        if (!androidBat.exists()) {

+            return false;

+        }

+

+        try {

+            final AdtConsoleSdkLog logger = new AdtConsoleSdkLog();

+

+            String command[] = new String[] {

+                    androidBat.getAbsolutePath(),

+                    "sdk"   //$NON-NLS-1$

+            };

+            Process process = Runtime.getRuntime().exec(command);

+            GrabProcessOutput.grabProcessOutput(

+                    process,

+                    Wait.ASYNC,

+                    new IProcessOutput() {

+                        @Override

+                        public void out(String line) {

+                            // Ignore stdout

+                        }

+

+                        @Override

+                        public void err(String line) {

+                            if (line != null) {

+                                logger.printf("[SDK Manager] %s", line);

+                            }

+                        }

+                    });

+        } catch (Exception ignore) {

+        }

+

+        return true;

+    }

+

+    /**

+     * Opens the SDK Manager bundled within ADT.

+     * The call is blocking and does not return till the SD Manager window is closed.

+     *

+     * @return True if the SDK location is known and the SDK Manager was started.

+     *   False if the SDK location is not set and we can't open a SDK Manager to

+     *   manage files in an unknown location.

+     */

+    public static boolean openAdtSdkManager() {

+        final Sdk sdk = Sdk.getCurrent();

+        if (sdk == null) {

+            return false;

+        }

+

+        // Runs the updater window, directing only warning/errors logs to the ADT console

+        // (normal log is just dropped, which is fine since the SDK Manager has its own

+        // log window now.)

+

+        SdkUpdaterWindow window = new SdkUpdaterWindow(

+                AdtPlugin.getDisplay().getActiveShell(),

+                new AdtConsoleSdkLog() {

+                    @Override

+                    public void printf(String msgFormat, Object... args) {

+                        // Do not show non-error/warning log in Eclipse.

+                    };

+                },

+                sdk.getSdkLocation(),

+                SdkInvocationContext.IDE);

+

+        ISdkChangeListener listener = new ISdkChangeListener() {

+            @Override

+            public void onSdkLoaded() {

+                // Ignore initial load of the SDK.

+            }

+

+            /**

+             * Unload all we can from the SDK before new packages are installed.

+             * Typically we need to get rid of references to dx from platform-tools

+             * and to any platform resource data.

+             * <p/>

+             * {@inheritDoc}

+             */

+            @Override

+            public void preInstallHook() {

+

+                // TODO we need to unload as much of as SDK as possible. Otherwise

+                // on Windows we end up with Eclipse locking some files and we can't

+                // replace them.

+                //

+                // At this point, we know what the user wants to install so it would be

+                // possible to pass in flags to know what needs to be unloaded. Typically

+                // we need to:

+                // - unload dex if platform-tools is going to be updated. There's a vague

+                //   attempt below at removing any references to dex and GCing. Seems

+                //   to do the trick.

+                // - unload any target that is going to be updated since it may have

+                //   resource data used by a current layout editor (e.g. data/*.ttf

+                //   and various data/res/*.xml).

+                //

+                // Most important we need to make sure there isn't a build going on

+                // and if there is one, either abort it or wait for it to complete and

+                // then we want to make sure we don't get any attempt to use the SDK

+                // before the postInstallHook is called.

+

+                if (sdk != null) {

+                    sdk.unloadTargetData(true /*preventReload*/);

+

+                    DexWrapper dx = sdk.getDexWrapper();

+                    dx.unload();

+                }

+            }

+

+            /**

+             * Nothing to do. We'll reparse the SDK later in onSdkReload.

+             * <p/>

+             * {@inheritDoc}

+             */

+            @Override

+            public void postInstallHook() {

+            }

+

+            /**

+             * Reparse the SDK in case anything was add/removed.

+             * <p/>

+             * {@inheritDoc}

+             */

+            @Override

+            public void onSdkReload() {

+                AdtPlugin.getDefault().reparseSdk();

+            }

+        };

+

+        window.addListener(listener);

+        window.open();

+

+        return true;

+    }

+

     @Override

     public void selectionChanged(IAction action, ISelection selection) {

         // nothing related to the current selection.

diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
index 3ae9f64..7536c2f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/BuildHelper.java
@@ -41,6 +41,7 @@
 import com.android.sdklib.internal.build.SignedJarBuilder;
 import com.android.sdklib.util.GrabProcessOutput;
 import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
@@ -512,7 +513,7 @@
         return compiledPaths;
     }
 
-    public void runProguard(File proguardConfig, File inputJar, String[] jarFiles,
+    public void runProguard(List<File> proguardConfigs, File inputJar, String[] jarFiles,
                             File obfuscatedJar, File logOutput)
             throws ProguardResultException, ProguardExecException, IOException {
         IAndroidTarget target = Sdk.getCurrent().getTarget(mProject);
@@ -521,7 +522,10 @@
         List<String> command = new ArrayList<String>();
         command.add(AdtPlugin.getOsAbsoluteProguard());
 
-        command.add("@" + quotePath(proguardConfig.getAbsolutePath())); //$NON-NLS-1$
+        for (File configFile : proguardConfigs) {
+            command.add("-include"); //$NON-NLS-1$
+            command.add(quotePath(configFile.getAbsolutePath()));
+        }
 
         command.add("-injars"); //$NON-NLS-1$
         StringBuilder sb = new StringBuilder(quotePath(inputJar.getAbsolutePath()));
@@ -1196,7 +1200,7 @@
 
         return GrabProcessOutput.grabProcessOutput(
                 process,
-                false /*waitForReaders*/,
+                Wait.WAIT_FOR_PROCESS,
                 new IProcessOutput() {
 
                     @SuppressWarnings("unused")
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java
index 426149e..eff883b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/preferences/AndroidPreferencePage.java
@@ -17,6 +17,7 @@
 package com.android.ide.eclipse.adt.internal.preferences;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
 import com.android.ide.eclipse.adt.internal.sdk.Sdk.ITargetChangeListener;
 import com.android.sdklib.IAndroidTarget;
@@ -140,13 +141,17 @@
             boolean ok = AdtPlugin.getDefault().checkSdkLocationAndId(fileName,
                     new AdtPlugin.CheckSdkErrorHandler() {
                 @Override
-                public boolean handleError(String message) {
+                public boolean handleError(
+                        CheckSdkErrorHandler.Solution solution,
+                        String message) {
                     setErrorMessage(message.replaceAll("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$
                     return false;  // Apply/OK must be disabled
                 }
 
                 @Override
-                public boolean handleWarning(String message) {
+                public boolean handleWarning(
+                        CheckSdkErrorHandler.Solution solution,
+                        String message) {
                     showMessage(message.replaceAll("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$
                     return true;  // Apply/OK must be enabled
                 }
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
index 1e5171c..93fe43d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/ExportHelper.java
@@ -16,6 +16,8 @@
 
 package com.android.ide.eclipse.adt.internal.project;
 
+import static com.android.sdklib.internal.project.ProjectProperties.PROPERTY_SDK;
+
 import com.android.ide.eclipse.adt.AdtConstants;
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.AdtUtils;
@@ -25,6 +27,7 @@
 import com.android.ide.eclipse.adt.internal.build.NativeLibInJarException;
 import com.android.ide.eclipse.adt.internal.build.ProguardExecException;
 import com.android.ide.eclipse.adt.internal.build.ProguardResultException;
+import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
 import com.android.ide.eclipse.adt.internal.sdk.ProjectState;
 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
 import com.android.ide.eclipse.adt.io.IFileWrapper;
@@ -58,6 +61,7 @@
 import java.io.OutputStream;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
@@ -66,8 +70,10 @@
  * Export helper to export release version of APKs.
  */
 public final class ExportHelper {
-
-    private final static String TEMP_PREFIX = "android_";  //$NON-NLS-1$
+    private static final String HOME_PROPERTY = "user.home";                    //$NON-NLS-1$
+    private static final String HOME_PROPERTY_REF = "${" + HOME_PROPERTY + '}'; //$NON-NLS-1$
+    private static final String SDK_PROPERTY_REF = "${" + PROPERTY_SDK + '}';   //$NON-NLS-1$
+    private final static String TEMP_PREFIX = "android_";                       //$NON-NLS-1$
 
     /**
      * Exports a release version of the application created by the given project.
@@ -75,7 +81,8 @@
      * @param outputFile the file to write
      * @param key the key to used for signing. Can be null.
      * @param certificate the certificate used for signing. Can be null.
-     * @param monitor
+     * @param monitor progress monitor
+     * @throws CoreException if an error occurs
      */
     public static void exportReleaseApk(IProject project, File outputFile, PrivateKey key,
             X509Certificate certificate, IProgressMonitor monitor) throws CoreException {
@@ -151,13 +158,46 @@
                     ProjectProperties.PROPERTY_PROGUARD_CONFIG);
 
             boolean runProguard = false;
-            File proguardConfigFile = null;
+            List<File> proguardConfigFiles = null;
             if (proguardConfig != null && proguardConfig.length() > 0) {
-                proguardConfigFile = new File(proguardConfig);
-                if (proguardConfigFile.isAbsolute() == false) {
-                    proguardConfigFile = new File(project.getLocation().toFile(), proguardConfig);
+                // Be tolerant with respect to file and path separators just like
+                // Ant is. Allow "/" in the property file to mean whatever the file
+                // separator character is:
+                if (File.separatorChar != '/' && proguardConfig.indexOf('/') != -1) {
+                    proguardConfig = proguardConfig.replace('/', File.separatorChar);
                 }
-                runProguard = proguardConfigFile.isFile();
+                // Also split path: no need to convert to File.pathSeparator because we'll
+                // be splitting the path ourselves right here, so just ensure that both
+                // ':' and ';' work:
+                if (proguardConfig.indexOf(';') != -1) {
+                    proguardConfig = proguardConfig.replace(';', ':');
+                }
+                String[] paths = proguardConfig.split(":"); //$NON-NLS-1$
+
+                for (String path : paths) {
+                    if (path.startsWith(SDK_PROPERTY_REF)) {
+                        path = AdtPrefs.getPrefs().getOsSdkFolder() +
+                                path.substring(SDK_PROPERTY_REF.length());
+                    } else if (path.startsWith(HOME_PROPERTY_REF)) {
+                        path = System.getProperty(HOME_PROPERTY) +
+                                path.substring(HOME_PROPERTY_REF.length());
+                    }
+                    File proguardConfigFile = new File(path);
+                    if (proguardConfigFile.isAbsolute() == false) {
+                        proguardConfigFile = new File(project.getLocation().toFile(), path);
+                    }
+                    if (proguardConfigFile.isFile()) {
+                        if (proguardConfigFiles == null) {
+                            proguardConfigFiles = new ArrayList<File>();
+                        }
+                        proguardConfigFiles.add(proguardConfigFile);
+                        runProguard = true;
+                    } else {
+                        throw new CoreException(new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
+                                "Invalid proguard configuration file path " + proguardConfigFile
+                                + " does not exist or is not a regular file", null));
+                    }
+                }
             }
 
             String[] dxInput;
@@ -188,7 +228,7 @@
                 obfuscatedJar.deleteOnExit();
 
                 // run proguard
-                helper.runProguard(proguardConfigFile, inputJar, jarFiles, obfuscatedJar,
+                helper.runProguard(proguardConfigFiles, inputJar, jarFiles, obfuscatedJar,
                         new File(project.getLocation().toFile(), SdkConstants.FD_PROGUARD));
 
                 // dx input is proguard's output
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java
index 2b3e2c2..96add71 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/AdtStartup.java
@@ -17,6 +17,7 @@
 package com.android.ide.eclipse.adt.internal.welcome;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
 import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
 import com.android.sdkstats.DdmsPreferenceStore;
 import com.android.sdkstats.SdkStatsService;
@@ -83,12 +84,16 @@
             boolean ok = AdtPlugin.getDefault().checkSdkLocationAndId(osSdkPath,
                     new AdtPlugin.CheckSdkErrorHandler() {
                 @Override
-                public boolean handleError(String message) {
+                public boolean handleError(
+                        CheckSdkErrorHandler.Solution solution,
+                        String message) {
                     return false;
                 }
 
                 @Override
-                public boolean handleWarning(String message) {
+                public boolean handleWarning(
+                        CheckSdkErrorHandler.Solution  solution,
+                        String message) {
                     return true;
                 }
             });
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java
index d418432..4e580fe 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/welcome/WelcomeWizardPage.java
@@ -16,6 +16,7 @@
 package com.android.ide.eclipse.adt.internal.welcome;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler;
 
 import org.eclipse.jface.dialogs.IMessageProvider;
 import org.eclipse.jface.wizard.WizardPage;
@@ -262,14 +263,18 @@
                     AdtPlugin.getDefault().checkSdkLocationAndId(path,
                             new AdtPlugin.CheckSdkErrorHandler() {
                         @Override
-                        public boolean handleError(String message) {
+                        public boolean handleError(
+                                CheckSdkErrorHandler.Solution solution,
+                                String message) {
                             message = message.replaceAll("\n", " "); //$NON-NLS-1$ //$NON-NLS-2$
                             errorReference.set(message);
                             return false;  // Apply/OK must be disabled
                         }
 
                         @Override
-                        public boolean handleWarning(String message) {
+                        public boolean handleWarning(
+                                CheckSdkErrorHandler.Solution solution,
+                                String message) {
                             message = message.replaceAll("\n", " "); //$NON-NLS-1$ //$NON-NLS-2$
                             warningReference.set(message);
                             return true;  // Apply/OK must be enabled
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java
index 4ce8230..8fcf902 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/export/ExportWizard.java
@@ -24,6 +24,7 @@
 import com.android.sdklib.internal.build.KeystoreHelper;
 import com.android.sdklib.util.GrabProcessOutput;
 import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
@@ -543,7 +544,7 @@
 
             int status = GrabProcessOutput.grabProcessOutput(
                     process,
-                    true /*waitForReaders*/,
+                    Wait.WAIT_FOR_READERS,
                     new IProcessOutput() {
                         @Override
                         public void out(String line) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java
index 97da3ab..7424d6c 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectCreator.java
@@ -606,7 +606,10 @@
             File libFolder = new File((String) parameters.get(PARAM_SDK_TOOLS_DIR),
                     SdkConstants.FD_LIB);
             addLocalFile(project,
-                    new File(libFolder, SdkConstants.FN_PROGUARD_CFG),
+                    new File(libFolder, SdkConstants.FN_PROJECT_PROGUARD_FILE),
+                    // Write ProGuard config files with the extension .pro which
+                    // is what is used in the ProGuard documentation and samples
+                    SdkConstants.FN_PROJECT_PROGUARD_FILE,
                     monitor);
 
             // Set output location
@@ -1080,13 +1083,14 @@
     /**
      * Adds a file to the root of the project
      * @param project the project to add the file to.
+     * @param destName the name to write the file as
      * @param source the file to add. It'll keep the same filename once copied into the project.
      * @throws FileNotFoundException
      * @throws CoreException
      */
-    private void addLocalFile(IProject project, File source, IProgressMonitor monitor)
-            throws FileNotFoundException, CoreException {
-        IFile dest = project.getFile(source.getName());
+    private void addLocalFile(IProject project, File source, String destName,
+            IProgressMonitor monitor) throws FileNotFoundException, CoreException {
+        IFile dest = project.getFile(destName);
         if (dest.exists() == false) {
             FileInputStream stream = new FileInputStream(source);
             dest.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
index d5bd895..ea78127 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
@@ -15,6 +15,9 @@
  */
 package com.android.ide.eclipse.adt.internal.wizards.newproject;
 
+import static com.android.sdklib.SdkConstants.FN_PROJECT_PROGUARD_FILE;
+import static com.android.sdklib.SdkConstants.OS_SDK_TOOLS_LIB_FOLDER;
+
 import com.android.ide.eclipse.adt.AdtPlugin;
 import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
 
@@ -26,6 +29,8 @@
 import org.eclipse.ui.INewWizard;
 import org.eclipse.ui.IWorkbench;
 
+import java.io.File;
+
 
 /**
  * A "New Android Project" Wizard.
@@ -105,6 +110,16 @@
 
     @Override
     public boolean performFinish() {
+        File file = new File(AdtPlugin.getOsSdkFolder(), OS_SDK_TOOLS_LIB_FOLDER + File.separator
+                + FN_PROJECT_PROGUARD_FILE);
+        if (!file.exists()) {
+            AdtPlugin.displayError("Tools Out of Date?",
+            String.format("It looks like you do not have the latest version of the "
+                    + "SDK Tools installed. Make sure you update via the SDK Manager "
+                    + "first. (Could not find %1$s)", file.getPath()));
+            return false;
+        }
+
         NewProjectCreator creator = new NewProjectCreator(mValues, getContainer());
         if (!(creator.createAndroidProjects())) {
             return false;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java
index 3db3353..6de6556 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/ProjectNamePage.java
@@ -18,8 +18,11 @@
 import static com.android.ide.eclipse.adt.AdtUtils.capitalize;
 import static com.android.ide.eclipse.adt.AdtUtils.stripWhitespace;
 import static com.android.ide.eclipse.adt.internal.wizards.newproject.ApplicationInfoPage.ACTIVITY_NAME_SUFFIX;
+import static com.android.sdklib.SdkConstants.FN_PROJECT_PROGUARD_FILE;
+import static com.android.sdklib.SdkConstants.OS_SDK_TOOLS_LIB_FOLDER;
 
 import com.android.ide.eclipse.adt.AdtPlugin;
+import com.android.ide.eclipse.adt.internal.VersionCheck;
 import com.android.ide.eclipse.adt.internal.project.AndroidManifestHelper;
 import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectWizardState.Mode;
 import com.android.sdklib.SdkConstants;
@@ -85,6 +88,15 @@
     private Button mBrowseButton;
     private Label mLocationLabel;
     private WorkingSetGroup mWorkingSetGroup;
+    /**
+     * Whether we've made sure the Tools are up to date (enough that all the
+     * resources required by the New Project wizard are present -- we don't
+     * necessarily check for newer versions than that here; that's done by
+     * {@link VersionCheck}, though that check doesn't <b>enforce</b> an update
+     * since it needs to allow the user to proceed to access the SDK manager
+     * etc.)
+     */
+    private boolean mCheckedSdkUptodate;
 
     /**
      * Create the wizard.
@@ -446,6 +458,20 @@
             }
         }
 
+        if (!mCheckedSdkUptodate) {
+            // Ensure that we have a recent enough version of the Tools that the right templates
+            // are available
+            File file = new File(AdtPlugin.getOsSdkFolder(), OS_SDK_TOOLS_LIB_FOLDER
+                    + File.separator + FN_PROJECT_PROGUARD_FILE);
+            if (!file.exists()) {
+                status = new Status(IStatus.ERROR, AdtPlugin.PLUGIN_ID,
+                        String.format("You do not have the latest version of the "
+                        + "SDK Tools installed: Please update. (Missing %1$s)", file.getPath()));
+            } else {
+                mCheckedSdkUptodate = true;
+            }
+        }
+
         // -- update UI & enable finish if there's no error
         setPageComplete(status == null || status.getSeverity() != IStatus.ERROR);
         if (status != null) {
diff --git a/files/ant/build.xml b/files/ant/build.xml
index 622d558..e47c3fe 100644
--- a/files/ant/build.xml
+++ b/files/ant/build.xml
@@ -766,13 +766,24 @@
                     </firstmatchmapper>
                 </pathconvert>
 
+                <!-- Turn the path property ${proguard.config} from an A:B:C property
+                     into a series of includes: -include A -include B -include C
+                     suitable for processing by the ProGuard task. Note - this does
+                     not include the leading '-include "' or the closing '"'; those
+                     are added under the <proguard> call below.
+                -->
+                <path id="proguard.configpath">
+                    <pathelement path="${proguard.config}"/>
+                </path>
+                <pathconvert pathsep='" -include "' property="proguard.configcmd" refid="proguard.configpath"/>
+
                 <mkdir   dir="${obfuscate.absolute.dir}" />
                 <delete file="${preobfuscate.jar.file}"/>
                 <delete file="${obfuscated.jar.file}"/>
                 <jar basedir="${out.classes.absolute.dir}"
                     destfile="${preobfuscate.jar.file}" />
                 <proguard>
-                    @${proguard.config}
+                    -include      "${proguard.configcmd}"
                     -injars       ${project.jars}
                     -outjars      "${obfuscated.jar.file}"
                     -libraryjars  ${android.libraryjars}
diff --git a/files/proguard-android.txt b/files/proguard-android.txt
new file mode 100644
index 0000000..b3d2fe1
--- /dev/null
+++ b/files/proguard-android.txt
@@ -0,0 +1,77 @@
+# This is a configuration file for ProGuard.
+# http://proguard.sourceforge.net/index.html#manual/usage.html
+
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-verbose
+
+# Optimization is turned off by default. Dex does not like code run
+# through the ProGuard optimize and preverify steps (and performs some
+# of these optimizations on its own).
+-dontoptimize
+-dontpreverify
+
+# If you want to enable optimization, you should include the
+# following:
+# -optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
+# -optimizationpasses 5
+# -allowaccessmodification
+#
+# Note that you cannot just include these flags in your own
+# configuration file; if you are including this file, optimization
+# will be turned off. You'll need to either edit this file, or
+# duplicate the contents of this file and remove the include of this
+# file from your project's proguard.config path property.
+
+-keepattributes *Annotation*
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgent
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+-keep public class * extends android.view.View {
+    public <init>(android.content.Context);
+    public <init>(android.content.Context, android.util.AttributeSet);
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+    public void set*(...);
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+   public void *(android.view.View);
+}
+
+# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+  public static final android.os.Parcelable$Creator *;
+}
+
+-keepclassmembers class **.R$* {
+    public static <fields>;
+}
+
+# The support library contains references to newer platform versions.
+# Don't warn about those in case this app is linking against an older
+# platform version.  We know about them, and they are safe.
+-dontwarn android.support.**
diff --git a/files/proguard-project.txt b/files/proguard-project.txt
new file mode 100644
index 0000000..f2fe155
--- /dev/null
+++ b/files/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
index 4ebc9ed..3f32727 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/client/api/LintDriver.java
@@ -21,7 +21,8 @@
 import static com.android.tools.lint.detector.api.LintConstants.DOT_CLASS;
 import static com.android.tools.lint.detector.api.LintConstants.DOT_JAR;
 import static com.android.tools.lint.detector.api.LintConstants.DOT_JAVA;
-import static com.android.tools.lint.detector.api.LintConstants.PROGUARD_CFG;
+import static com.android.tools.lint.detector.api.LintConstants.OLD_PROGUARD_FILE;
+import static com.android.tools.lint.detector.api.LintConstants.PROGUARD_FILE;
 import static com.android.tools.lint.detector.api.LintConstants.RES_FOLDER;
 import static com.android.tools.lint.detector.api.LintConstants.SUPPRESS_ALL;
 import static com.android.tools.lint.detector.api.LintConstants.SUPPRESS_LINT;
@@ -46,6 +47,8 @@
 import com.android.tools.lint.detector.api.Severity;
 import com.android.tools.lint.detector.api.XmlContext;
 import com.google.common.annotations.Beta;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.io.ByteStreams;
@@ -215,7 +218,7 @@
                             mScope.add(Scope.MANIFEST);
                         } else if (name.endsWith(".xml")) {
                             mScope.add(Scope.RESOURCE_FILE);
-                        } else if (name.equals(PROGUARD_CFG)) {
+                        } else if (name.equals(PROGUARD_FILE) || name.equals(OLD_PROGUARD_FILE)) {
                             mScope.add(Scope.PROGUARD_FILE);
                         } else if (name.equals(RES_FOLDER)
                                 || file.getParent().equals(RES_FOLDER)) {
@@ -225,6 +228,8 @@
                             mScope.add(Scope.JAVA_FILE);
                         } else if (name.endsWith(DOT_CLASS)) {
                             mScope.add(Scope.CLASS_FILE);
+                        } else if (name.equals(OLD_PROGUARD_FILE) || name.equals(PROGUARD_FILE)) {
+                            mScope.add(Scope.PROGUARD_FILE);
                         }
                     }
                 } else {
@@ -740,18 +745,50 @@
         }
 
         if (project == main && mScope.contains(Scope.PROGUARD_FILE)) {
-            List<Detector> detectors = mScopeDetectors.get(Scope.PROGUARD_FILE);
-            if (detectors != null) {
-                File file = new File(project.getDir(), PROGUARD_CFG);
+            checkProGuard(project, main);
+        }
+    }
+
+    private void checkProGuard(Project project, Project main) {
+        List<Detector> detectors = mScopeDetectors.get(Scope.PROGUARD_FILE);
+        if (detectors != null) {
+            Project p = main != null ? main : project;
+            List<File> files = new ArrayList<File>();
+            String paths = p.getProguardPath();
+            if (paths != null) {
+                Splitter splitter = Splitter.on(CharMatcher.anyOf(":;")); //$NON-NLS-1$
+                for (String path : splitter.split(paths)) {
+                    if (path.contains("${")) { //$NON-NLS-1$
+                        // Don't analyze the global/user proguard files
+                        continue;
+                    }
+                    File file = new File(path);
+                    if (!file.isAbsolute()) {
+                        file = new File(project.getDir(), path);
+                    }
+                    if (file.exists()) {
+                        files.add(file);
+                    }
+                }
+            }
+            if (files.isEmpty()) {
+                File file = new File(project.getDir(), OLD_PROGUARD_FILE);
                 if (file.exists()) {
-                    Context context = new Context(this, project, main, file);
-                    fireEvent(EventType.SCANNING_FILE, context);
-                    for (Detector detector : detectors) {
-                        if (detector.appliesTo(context, file)) {
-                            detector.beforeCheckFile(context);
-                            detector.run(context);
-                            detector.afterCheckFile(context);
-                        }
+                    files.add(file);
+                }
+                file = new File(project.getDir(), PROGUARD_FILE);
+                if (file.exists()) {
+                    files.add(file);
+                }
+            }
+            for (File file : files) {
+                Context context = new Context(this, project, main, file);
+                fireEvent(EventType.SCANNING_FILE, context);
+                for (Detector detector : detectors) {
+                    if (detector.appliesTo(context, file)) {
+                        detector.beforeCheckFile(context);
+                        detector.run(context);
+                        detector.afterCheckFile(context);
                     }
                 }
             }
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
index cb47f92..6788652 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/LintConstants.java
@@ -242,7 +242,9 @@
 
     // Filenames and folder names
     public static final String ANDROID_MANIFEST_XML = "AndroidManifest.xml"; //$NON-NLS-1$
-    public static final String PROGUARD_CFG = "proguard.cfg";          //$NON-NLS-1$
+    public static final String OLD_PROGUARD_FILE = "proguard.cfg";     //$NON-NLS-1$
+    public static final String PROGUARD_FILE = "proguard-project.txt"; //$NON-NLS-1$
+
     public static final String RES_FOLDER = "res";                     //$NON-NLS-1$
     public static final String DOT_XML = ".xml";                       //$NON-NLS-1$
     public static final String DOT_GIF = ".gif";                       //$NON-NLS-1$
@@ -283,6 +285,7 @@
 
     // Project properties
     public static final String ANDROID_LIBRARY = "android.library";     //$NON-NLS-1$
+    public static final String PROGUARD_CONFIG = "proguard.config";     //$NON-NLS-1$
     public static final String ANDROID_LIBRARY_REFERENCE_FORMAT = "android.library.reference.%1$d";//$NON-NLS-1$
     public static final String PROJECT_PROPERTIES = "project.properties";//$NON-NLS-1$
 
diff --git a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
index 910ee2f..d0de34c 100644
--- a/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
+++ b/lint/libs/lint_api/src/com/android/tools/lint/detector/api/Project.java
@@ -23,6 +23,7 @@
 import static com.android.tools.lint.detector.api.LintConstants.ATTR_MIN_SDK_VERSION;
 import static com.android.tools.lint.detector.api.LintConstants.ATTR_PACKAGE;
 import static com.android.tools.lint.detector.api.LintConstants.ATTR_TARGET_SDK_VERSION;
+import static com.android.tools.lint.detector.api.LintConstants.PROGUARD_CONFIG;
 import static com.android.tools.lint.detector.api.LintConstants.PROJECT_PROPERTIES;
 import static com.android.tools.lint.detector.api.LintConstants.TAG_USES_SDK;
 import static com.android.tools.lint.detector.api.LintConstants.VALUE_TRUE;
@@ -71,6 +72,7 @@
     private int mTargetSdk = -1;
     private boolean mLibrary;
     private String mName;
+    private String mProguardPath;
 
     /** The SDK info, if any */
     private SdkInfo mSdkInfo;
@@ -121,6 +123,7 @@
                     properties.load(is);
                     String value = properties.getProperty(ANDROID_LIBRARY);
                     mLibrary = VALUE_TRUE.equals(value);
+                    mProguardPath = properties.getProperty(PROGUARD_CONFIG);
 
                     for (int i = 1; i < 1000; i++) {
                         String key = String.format(ANDROID_LIBRARY_REFERENCE_FORMAT, i);
@@ -545,6 +548,17 @@
     }
 
     /**
+     * Returns the proguard path configured for this project, or null if ProGuard is
+     * not configured.
+     *
+     * @return the proguard path, or null
+     */
+    @Nullable
+    public String getProguardPath() {
+        return mProguardPath;
+    }
+
+    /**
      * Returns the name of the project
      *
      * @return the name of the project, never null
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
index 258a267..3af53ad 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/BuiltinIssueRegistry.java
@@ -53,7 +53,7 @@
     private static final List<Issue> sIssues;
 
     static {
-        final int initialCapacity = 81;
+        final int initialCapacity = 82;
         List<Issue> issues = new ArrayList<Issue>(initialCapacity);
 
         issues.add(AccessibilityDetector.ISSUE);
@@ -89,7 +89,8 @@
         issues.add(TranslationDetector.MISSING);
         issues.add(HardcodedValuesDetector.ISSUE);
         issues.add(Utf8Detector.ISSUE);
-        issues.add(ProguardDetector.ISSUE);
+        issues.add(ProguardDetector.WRONGKEEP);
+        issues.add(ProguardDetector.SPLITCONFIG);
         issues.add(PxUsageDetector.ISSUE);
         issues.add(TextFieldDetector.ISSUE);
         issues.add(TextViewDetector.ISSUE);
diff --git a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java
index 95de739..c062507 100644
--- a/lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java
+++ b/lint/libs/lint_checks/src/com/android/tools/lint/checks/ProguardDetector.java
@@ -16,6 +16,9 @@
 
 package com.android.tools.lint.checks;
 
+import static com.android.tools.lint.detector.api.LintConstants.PROGUARD_CONFIG;
+import static com.android.tools.lint.detector.api.LintConstants.PROJECT_PROPERTIES;
+
 import com.android.tools.lint.detector.api.Category;
 import com.android.tools.lint.detector.api.Context;
 import com.android.tools.lint.detector.api.Detector;
@@ -34,10 +37,10 @@
 public class ProguardDetector extends Detector {
 
     /** The main issue discovered by this detector */
-    public static final Issue ISSUE = Issue.create(
+    public static final Issue WRONGKEEP = Issue.create(
             "Proguard", //$NON-NLS-1$
-            "Looks for problems in proguard.cfg files",
-            "Using -keepclasseswithmembernames in a proguard.cfg file is not " +
+            "Looks for problems in proguard config files",
+            "Using -keepclasseswithmembernames in a proguard config file is not " +
             "correct; it can cause some symbols to be renamed which should not be.\n" +
             "Earlier versions of ADT used to create proguard.cfg files with the " +
             "wrong format. Instead of -keepclasseswithmembernames use " +
@@ -51,25 +54,105 @@
             EnumSet.of(Scope.PROGUARD_FILE)).setMoreInfo(
             "http://http://code.google.com/p/android/issues/detail?id=16384"); //$NON-NLS-1$
 
+    /** Finds ProGuard files that contain non-project specific configuration
+     * locally and suggests replacing it with an include path */
+    public static final Issue SPLITCONFIG = Issue.create(
+            "ProguardSplit", //$NON-NLS-1$
+            "Checks for old proguard.cfg files that contain generic Android rules",
+
+            "Earlier versions of the Android tools bundled a single \"proguard.cfg\" file " +
+            "containing a ProGuard configuration file suitable for Android shrinking and " +
+            "obfuscation. However, that version was copied into new projects, which " +
+            "means that it does not continue to get updated as we improve the default " +
+            "ProGuard rules for Android.\n" +
+            "\n" +
+            "In the new version of the tools, we have split the ProGuard configuration " +
+            "into two halves:\n" +
+            "* A simple configuration file containing only project-specific flags, in " +
+            "your project\n" +
+            "* A generic configuration file containing the recommended set of ProGuard " +
+            "options for Android projects. This generic file lives in the SDK install " +
+            "directory which means that it gets updated along with the tools.\n" +
+            "\n" +
+            "In order for this to work, the proguard.config property in the " +
+            "project.properties file now refers to a path, so you can reference both " +
+            "the generic file as well as your own (and any additional files too).\n" +
+            "\n" +
+            "To migrate your project to the new setup, create a new proguard-project.txt file " +
+            "in your project containing any project specific ProGuard flags as well as " +
+            "any customizations you have made, then update your project.properties file " +
+            "to contain:\n" +
+            "proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt",
+
+            Category.CORRECTNESS,
+            3,
+            Severity.WARNING,
+            ProguardDetector.class,
+            EnumSet.of(Scope.PROGUARD_FILE));
+
     @Override
     public void run(Context context) {
         String contents = context.getContents();
         if (contents != null) {
-            int index = contents.indexOf(
-                    // Old pattern:
-                    "-keepclasseswithmembernames class * {\n" + //$NON-NLS-1$
-                    "    public <init>(android.");              //$NON-NLS-1$
-            if (index != -1) {
-                context.report(ISSUE,
-                    Location.create(context.file, contents, index, index),
-                    "Obsolete proguard file; use -keepclasseswithmembers instead of -keepclasseswithmembernames", null);
+            if (context.isEnabled(WRONGKEEP)) {
+                int index = contents.indexOf(
+                        // Old pattern:
+                        "-keepclasseswithmembernames class * {\n" + //$NON-NLS-1$
+                        "    public <init>(android.");              //$NON-NLS-1$
+                if (index != -1) {
+                    context.report(WRONGKEEP,
+                            Location.create(context.file, contents, index, index),
+                            "Obsolete ProGuard file; use -keepclasseswithmembers instead of " +
+                            "-keepclasseswithmembernames", null);
+                }
+            }
+            if (context.isEnabled(SPLITCONFIG)) {
+                int index = contents.indexOf("-keep public class * extends android.app.Activity");
+                if (index != -1) {
+                    // Only complain if project.properties actually references this file;
+                    // no need to bother the users who got a default proguard.cfg file
+                    // when they created their projects but haven't actually hooked it up
+                    // to shrinking & obfuscation.
+                    File propertyFile = new File(context.file.getParentFile(), PROJECT_PROPERTIES);
+                    if (!propertyFile.exists()) {
+                        return;
+                    }
+                    String properties = context.getClient().readFile(propertyFile);
+                    int i = properties.indexOf(PROGUARD_CONFIG);
+                    if (i == -1) {
+                        return;
+                    }
+                    // Make sure the entry isn't just commented out, such as
+                    // # To enable ProGuard to shrink and obfuscate your code, uncomment this:
+                    // #proguard.config=proguard.cfg
+                    for (; i >= 0; i--) {
+                        char c = properties.charAt(i);
+                        if (c == '#') {
+                            return;
+                        }
+                        if (c == '\n') {
+                            break;
+                        }
+                    }
+                    if (properties.contains(PROGUARD_CONFIG)) {
+                        context.report(SPLITCONFIG,
+                            Location.create(context.file, contents, index, index),
+                            String.format(
+                            "Local ProGuard configuration contains general Android " +
+                            "configuration: Inherit these settings instead? " +
+                            "Modify project.properties to define " +
+                            "proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:%1$s" +
+                            " and then keep only project-specific configuration here",
+                            context.file.getName()), null);
+                    }
+                }
             }
         }
     }
 
     @Override
     public boolean appliesTo(Context context, File file) {
-        return file.getName().equals("proguard.cfg"); //$NON-NLS-1$
+        return true;
     }
 
     @Override
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java
index 019effd..f3d872b 100644
--- a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/ProguardDetectorTest.java
@@ -27,8 +27,60 @@
 
     public void testProguard() throws Exception {
         assertEquals(
-                "proguard.cfg:21: Error: Obsolete proguard file; use -keepclasseswithmembers " +
+                "proguard.cfg:21: Error: Obsolete ProGuard file; use -keepclasseswithmembers " +
                     "instead of -keepclasseswithmembernames",
                 lintFiles("proguard.cfg"));
     }
+
+    public void testProguardNewPath() throws Exception {
+        assertEquals(
+                "proguard-project.txt:21: Error: Obsolete ProGuard file; use " +
+                        "-keepclasseswithmembers instead of -keepclasseswithmembernames",
+                lintFiles("proguard.cfg=>proguard-project.txt"));
+    }
+
+    public void testProguardRandomName() throws Exception {
+        assertEquals(
+                "myfile.txt:21: Error: Obsolete ProGuard file; use -keepclasseswithmembers " +
+                "instead of -keepclasseswithmembernames\n" +
+                "myfile.txt:8: Warning: Local ProGuard configuration contains general " +
+                "Android configuration: Inherit these settings instead? Modify " +
+                "project.properties to define proguard.config=${sdk.dir}/tools/proguard/" +
+                "proguard-android.txt:myfile.txt and then keep only project-specific " +
+                "configuration here",
+                lintProject(
+                        "proguard.cfg=>myfile.txt",
+                        "proguard.properties=>project.properties"));
+    }
+
+    public void testSilent() throws Exception {
+        assertEquals(
+                "No warnings.",
+
+                lintFiles(
+                        "proguard.pro=>proguard.cfg",
+                        "project.properties1=>project.properties"));
+    }
+
+    public void testSilent2() throws Exception {
+        assertEquals(
+                "No warnings.",
+
+                lintFiles(
+                        "proguard.pro=>proguard.cfg",
+                        "project.properties3=>project.properties"));
+    }
+
+    public void testSplit() throws Exception {
+        assertEquals(
+                "proguard.cfg:14: Warning: Local ProGuard configuration contains general " +
+                "Android configuration: Inherit these settings instead? Modify " +
+                "project.properties to define " +
+                "proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard.cfg " +
+                "and then keep only project-specific configuration here",
+
+                lintFiles(
+                        "proguard.pro=>proguard.cfg",
+                        "project.properties2=>project.properties"));
+    }
 }
diff --git a/files/proguard.cfg b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.pro
similarity index 100%
rename from files/proguard.cfg
rename to lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.pro
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.properties b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.properties
new file mode 100644
index 0000000..989c3c7
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/proguard.properties
@@ -0,0 +1,2 @@
+target=android-14
+proguard.config=${sdk.dir}/foo.cfg:${user.home}/bar.pro;myfile.txt
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties1 b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties1
new file mode 100644
index 0000000..2b783dd
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties1
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+#proguard.config=proguard.cfg
+
+# Project target.
+target=android-3
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties2 b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties2
new file mode 100644
index 0000000..d9a28ec
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties2
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+proguard.config=proguard.cfg
+
+# Project target.
+target=android-3
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties3 b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties3
new file mode 100644
index 0000000..3cb9d31
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties3
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-3
diff --git a/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties4 b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties4
new file mode 100644
index 0000000..fca9311
--- /dev/null
+++ b/lint/libs/lint_checks/tests/src/com/android/tools/lint/checks/data/project.properties4
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this:
+proguard.config=${sdk.dir}/tools/proguard/android-defaults.pro:proguard.pro
+
+# Project target.
+target=android-3
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
index 4f3ed9f..e21e14f 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
@@ -166,8 +166,10 @@
      */
     public final static String FN_GDBSERVER = "gdbserver";              //$NON-NLS-1$
 
-    /** default proguard config file */
-    public final static String FN_PROGUARD_CFG = "proguard.cfg";        //$NON-NLS-1$
+    /** global Android proguard config file */
+    public final static String FN_ANDROID_PROGUARD_FILE = "proguard-android.txt";   //$NON-NLS-1$
+    /** default proguard config file with new file extension (for project specific stuff) */
+    public final static String FN_PROJECT_PROGUARD_FILE = "proguard-project.txt";   //$NON-NLS-1$
 
     /* Folder Names for Android Projects . */
 
@@ -385,7 +387,6 @@
     /** SDK property: default skin */
     public final static String PROP_SDK_DEFAULT_SKIN = "sdk.skin.default"; //$NON-NLS-1$
 
-
     /* Android Class Constants */
     public final static String CLASS_ACTIVITY = "android.app.Activity"; //$NON-NLS-1$
     public final static String CLASS_APPLICATION = "android.app.Application"; //$NON-NLS-1$
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
index 436f2e8..db3cc33 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/avd/AvdManager.java
@@ -28,6 +28,7 @@
 import com.android.sdklib.internal.project.ProjectProperties;
 import com.android.sdklib.util.GrabProcessOutput;
 import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
 import com.android.util.Pair;
 
 import java.io.File;
@@ -1398,7 +1399,7 @@
 
             int status = GrabProcessOutput.grabProcessOutput(
                     process,
-                    true /*waitForReaders*/,
+                    Wait.WAIT_FOR_READERS,
                     new IProcessOutput() {
                         @Override
                         public void out(String line) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java
index 06f5351..af5b401 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/build/KeystoreHelper.java
@@ -20,6 +20,7 @@
 import com.android.sdklib.internal.build.DebugKeyProvider.KeytoolException;
 import com.android.sdklib.util.GrabProcessOutput;
 import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;
+import com.android.sdklib.util.GrabProcessOutput.Wait;
 
 import java.io.File;
 import java.io.IOException;
@@ -107,7 +108,7 @@
             Process process = Runtime.getRuntime().exec(commandArray);
             result = GrabProcessOutput.grabProcessOutput(
                     process,
-                    true /*waitForReaders*/,
+                    Wait.WAIT_FOR_READERS,
                     new IProcessOutput() {
                         @Override
                         public void out(String line) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
index c3d7993..721d165 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
@@ -369,8 +369,8 @@
                     keywords);
 
             // install the proguard config file.
-            installTemplate(SdkConstants.FN_PROGUARD_CFG,
-                    new File(projectFolder, SdkConstants.FN_PROGUARD_CFG),
+            installTemplate(SdkConstants.FN_PROJECT_PROGUARD_FILE,
+                    new File(projectFolder, SdkConstants.FN_PROJECT_PROGUARD_FILE),
                     null /*keywords*/);
         } catch (Exception e) {
             mLog.error(e, null);
@@ -751,8 +751,10 @@
 
         if (hasProguard == false) {
             try {
-                installTemplate(SdkConstants.FN_PROGUARD_CFG,
-                        new File(projectFolder, SdkConstants.FN_PROGUARD_CFG),
+                installTemplate(SdkConstants.FN_PROJECT_PROGUARD_FILE,
+                        // Write ProGuard config files with the extension .pro which
+                        // is what is used in the ProGuard documentation and samples
+                        new File(projectFolder, SdkConstants.FN_PROJECT_PROGUARD_FILE),
                         null /*placeholderMap*/);
             } catch (ProjectCreateException e) {
                 mLog.error(e, null);
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
index 3a73bef..2bb6b71 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectProperties.java
@@ -16,6 +16,11 @@
 
 package com.android.sdklib.internal.project;
 
+import static com.android.sdklib.SdkConstants.FD_PROGUARD;
+import static com.android.sdklib.SdkConstants.FD_TOOLS;
+import static com.android.sdklib.SdkConstants.FN_ANDROID_PROGUARD_FILE;
+import static com.android.sdklib.SdkConstants.FN_PROJECT_PROGUARD_FILE;
+
 import com.android.io.FolderWrapper;
 import com.android.io.IAbstractFile;
 import com.android.io.IAbstractFolder;
@@ -24,6 +29,7 @@
 import com.android.sdklib.SdkConstants;
 
 import java.io.BufferedReader;
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
@@ -163,7 +169,7 @@
             "# This file is automatically generated by Android Tools.\n" +
             "# Do not modify this file -- YOUR CHANGES WILL BE ERASED!\n" +
             "#\n" +
-            "# This file must *NOT* be checked in Version Control Systems,\n" +
+            "# This file must *NOT* be checked into Version Control Systems,\n" +
             "# as it contains information specific to your local configuration.\n" +
             "\n";
 
@@ -174,16 +180,22 @@
            "#\n" +
            "# This file must be checked in Version Control Systems.\n" +
            "#\n" +
-           "# To customize properties used by the Ant build system use,\n" +
+           "# To customize properties used by the Ant build system edit\n" +
            "# \"ant.properties\", and override values to adapt the script to your\n" +
            "# project structure.\n" +
+           "#\n" +
+           "# To enable ProGuard to shrink and obfuscate your code, uncomment this "
+               + "(available properties: sdk.dir, user.home):\n" +
+           "#" + PROPERTY_PROGUARD_CONFIG + "=${" + PROPERTY_SDK +"}" + File.separator
+               + FD_TOOLS + File.separator + FD_PROGUARD + File.separator
+               + FN_ANDROID_PROGUARD_FILE + ':' + FN_PROJECT_PROGUARD_FILE +'\n' +
            "\n";
 
     private final static String BUILD_HEADER =
 //          1-------10--------20--------30--------40--------50--------60--------70--------80
            "# This file is used to override default values used by the Ant build system.\n" +
            "#\n" +
-           "# This file must be checked in Version Control Systems, as it is\n" +
+           "# This file must be checked into Version Control Systems, as it is\n" +
            "# integral to the build system of your project.\n" +
            "\n" +
            "# This file is only used by the Ant script.\n" +
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
index 9e50430..2e2396f 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ArchiveInstaller.java
@@ -25,6 +25,7 @@
 import com.android.sdklib.repository.RepoConstants;

 import com.android.sdklib.util.GrabProcessOutput;

 import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;

+import com.android.sdklib.util.GrabProcessOutput.Wait;

 

 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;

 import org.apache.commons.compress.archivers.zip.ZipFile;

@@ -598,7 +599,7 @@
                 Process process = Runtime.getRuntime().exec(command);

                 int retCode = GrabProcessOutput.grabProcessOutput(

                         process,

-                        true /*waitForReaders*/,

+                        Wait.WAIT_FOR_READERS,

                         new IProcessOutput() {

                             @Override

                             public void out(String line) {

diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
index ffd561f..3ddacb4 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
@@ -25,6 +25,7 @@
 import com.android.sdklib.repository.SdkRepoConstants;

 import com.android.sdklib.util.GrabProcessOutput;

 import com.android.sdklib.util.GrabProcessOutput.IProcessOutput;

+import com.android.sdklib.util.GrabProcessOutput.Wait;

 

 import org.w3c.dom.Node;

 

@@ -276,7 +277,7 @@
             final String tag = scriptName;

             status = GrabProcessOutput.grabProcessOutput(

                     proc,

-                    false /*waitForReaders*/,

+                    Wait.WAIT_FOR_PROCESS,

                     new IProcessOutput() {

                         @Override

                         public void out(String line) {

diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java
index b470153..2935493 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/util/GrabProcessOutput.java
@@ -25,6 +25,35 @@
 
 public class GrabProcessOutput {
 
+    public enum Wait {
+        /**
+         * Doesn't wait for the exec to complete.
+         * This still monitors the output but does not wait for the process to finish.
+         * In this mode the process return code is unknown and always 0.
+         */
+        ASYNC,
+        /**
+         * This waits for the process to finish.
+         * In this mode, {@link GrabProcessOutput#grabProcessOutput} returns the
+         * error code from the process.
+         * In some rare cases and depending on the OS, the process might not have
+         * finished dumping data into stdout/stderr.
+         * <p/>
+         * Use this when you don't particularly care for the output but instead
+         * care for the return code of the executed process.
+         */
+        WAIT_FOR_PROCESS,
+        /**
+         * This waits for the process to finish <em>and</em> for the stdout/stderr
+         * threads to complete.
+         * In this mode, {@link GrabProcessOutput#grabProcessOutput} returns the
+         * error code from the process.
+         * <p/>
+         * Use this one when capturing all the output from the process is important.
+         */
+        WAIT_FOR_READERS,
+    }
+
     public interface IProcessOutput {
         /**
          * Processes an stdout message line.
@@ -46,13 +75,13 @@
      * @param output Optional object to capture stdout/stderr.
      *      Note that on Windows capturing the output is not optional. If output is null
      *      the stdout/stderr will be captured and discarded.
-     * @param waitForReaders True to wait for the reader threads to finish.
+     * @param waitMode Whether to wait for the process and/or the readers to finish.
      * @return the process return code.
      * @throws InterruptedException if {@link Process#waitFor()} was interrupted.
      */
     public static int grabProcessOutput(
             @NonNull final Process process,
-            boolean waitForReaders,
+            Wait waitMode,
             @Nullable final IProcessOutput output) throws InterruptedException {
         // read the lines as they come. if null is returned, it's
         // because the process finished
@@ -104,10 +133,14 @@
         threadErr.start();
         threadOut.start();
 
+        if (waitMode == Wait.ASYNC) {
+            return 0;
+        }
+
         // it looks like on windows process#waitFor() can return
         // before the thread have filled the arrays, so we wait for both threads and the
         // process itself.
-        if (waitForReaders) {
+        if (waitMode == Wait.WAIT_FOR_READERS) {
             try {
                 threadErr.join();
             } catch (InterruptedException e) {