Replace icon template with new style and multiple densities.

The icon in the templates of ADT was medium density only.
I added new densities (high and low), as well as updated to
the new Eclair style. Also added a version for Ant project.

Updated ADT and sdklib to deal with creating new projects
with all 3 icons.

In case of Ant project, this is done only if the icons
are present in the target platforms.

For ADT, this is done only if the project target donut
or later. Older project still have only one icon located
in drawable/

Change-Id: I77069a1e4902ef395d490526aabc40a26e33d4ca
diff --git a/build/sdk.atree b/build/sdk.atree
index 20542a2..1749915 100644
--- a/build/sdk.atree
+++ b/build/sdk.atree
@@ -58,6 +58,9 @@
 development/tools/scripts/android_rules.xml platforms/${PLATFORM_NAME}/templates/android_rules.xml
 development/tools/scripts/android_test_rules.xml platforms/${PLATFORM_NAME}/templates/android_test_rules.xml
 development/tools/scripts/build.template tools/lib/build.template
+development/tools/scripts/icon_ldpi.png platforms/${PLATFORM_NAME}/templates/icon_ldpi.png
+development/tools/scripts/icon_mdpi.png platforms/${PLATFORM_NAME}/templates/icon_mdpi.png
+development/tools/scripts/icon_hdpi.png platforms/${PLATFORM_NAME}/templates/icon_hdpi.png
 
 # emacs support
 development/tools/scripts/android.el tools/lib/android.el
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
index d8989c2..df333a5 100644
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/wizards/newproject/NewProjectWizard.java
@@ -20,6 +20,7 @@
 import com.android.ide.eclipse.adt.AndroidConstants;
 import com.android.ide.eclipse.adt.internal.project.AndroidNature;
 import com.android.ide.eclipse.adt.internal.project.ProjectHelper;
+import com.android.ide.eclipse.adt.internal.resources.configurations.PixelDensityQualifier.Density;
 import com.android.ide.eclipse.adt.internal.sdk.Sdk;
 import com.android.ide.eclipse.adt.internal.wizards.newproject.NewProjectCreationPage.IMainInfo;
 import com.android.ide.eclipse.adt.internal.wizards.newproject.NewTestProjectCreationPage.TestInfo;
@@ -132,6 +133,12 @@
         SdkConstants.FD_ASSETS + AndroidConstants.WS_SEP;
     private static final String DRAWABLE_DIRECTORY =
         SdkConstants.FD_DRAWABLE + AndroidConstants.WS_SEP;
+    private static final String DRAWABLE_HDPI_DIRECTORY =
+        SdkConstants.FD_DRAWABLE + "-" + Density.HIGH.getValue() + AndroidConstants.WS_SEP;   //$NON-NLS-1$
+    private static final String DRAWABLE_MDPI_DIRECTORY =
+        SdkConstants.FD_DRAWABLE + "-" + Density.MEDIUM.getValue() + AndroidConstants.WS_SEP; //$NON-NLS-1$
+    private static final String DRAWABLE_LDPI_DIRECTORY =
+        SdkConstants.FD_DRAWABLE + "-" + Density.LOW.getValue() + AndroidConstants.WS_SEP;    //$NON-NLS-1$
     private static final String LAYOUT_DIRECTORY =
         SdkConstants.FD_LAYOUT + AndroidConstants.WS_SEP;
     private static final String VALUES_DIRECTORY =
@@ -159,7 +166,10 @@
             + "strings.template"; //$NON-NLS-1$
     private static final String TEMPLATE_STRING = TEMPLATES_DIRECTORY
             + "string.template"; //$NON-NLS-1$
-    private static final String ICON = "icon.png"; //$NON-NLS-1$
+    private static final String PROJECT_ICON = "icon.png"; //$NON-NLS-1$
+    private static final String ICON_HDPI = "icon_hdpi.png"; //$NON-NLS-1$
+    private static final String ICON_MDPI = "icon_mdpi.png"; //$NON-NLS-1$
+    private static final String ICON_LDPI = "icon_ldpi.png"; //$NON-NLS-1$
 
     private static final String STRINGS_FILE = "strings.xml";       //$NON-NLS-1$
 
@@ -170,7 +180,10 @@
     private static final String[] DEFAULT_DIRECTORIES = new String[] {
             BIN_DIRECTORY, RES_DIRECTORY, ASSETS_DIRECTORY };
     private static final String[] RES_DIRECTORIES = new String[] {
-            DRAWABLE_DIRECTORY, LAYOUT_DIRECTORY, VALUES_DIRECTORY};
+            DRAWABLE_DIRECTORY, LAYOUT_DIRECTORY, VALUES_DIRECTORY };
+    private static final String[] RES_DENSITY_ENABLED_DIRECTORIES = new String[] {
+            DRAWABLE_HDPI_DIRECTORY, DRAWABLE_MDPI_DIRECTORY, DRAWABLE_LDPI_DIRECTORY,
+            LAYOUT_DIRECTORY, VALUES_DIRECTORY };
 
     private static final String PROJECT_LOGO_LARGE = "icons/android_large.png"; //$NON-NLS-1$
     private static final String JAVA_ACTIVITY_TEMPLATE = "java_file.template";  //$NON-NLS-1$
@@ -587,6 +600,10 @@
             Map<String, String> dictionary)
                 throws CoreException, IOException {
 
+        // get the project target
+        IAndroidTarget target = (IAndroidTarget) parameters.get(PARAM_SDK_TARGET);
+        boolean legacy = target.getVersion().getApiLevel() < 4;
+
         // Create project and open it
         project.create(description, new SubProgressMonitor(monitor, 10));
         if (monitor.isCanceled()) throw new OperationCanceledException();
@@ -605,7 +622,11 @@
         addDefaultDirectories(project, AndroidConstants.WS_ROOT, sourceFolders, monitor);
 
         // Create the resource folders in the project if they don't already exist.
-        addDefaultDirectories(project, RES_DIRECTORY, RES_DIRECTORIES, monitor);
+        if (legacy) {
+            addDefaultDirectories(project, RES_DIRECTORY, RES_DIRECTORIES, monitor);
+        } else {
+            addDefaultDirectories(project, RES_DIRECTORY, RES_DENSITY_ENABLED_DIRECTORIES, monitor);
+        }
 
         // Setup class path: mark folders as source folders
         IJavaProject javaProject = JavaCore.create(project);
@@ -624,7 +645,7 @@
             addManifest(project, parameters, dictionary, monitor);
 
             // add the default app icon
-            addIcon(project, monitor);
+            addIcon(project, legacy, monitor);
 
             // Create the default package components
             addSampleCode(project, sourceFolders[0], parameters, dictionary, monitor);
@@ -650,7 +671,8 @@
                 // the currently-empty current list.
                 desc.setReferencedProjects(new IProject[] { refProject });
 
-                project.setDescription(desc, IResource.KEEP_HISTORY, new SubProgressMonitor(monitor, 10));
+                project.setDescription(desc, IResource.KEEP_HISTORY,
+                        new SubProgressMonitor(monitor, 10));
 
                 IClasspathEntry entry = JavaCore.newProjectEntry(
                         refProject.getFullPath(), //path
@@ -664,8 +686,7 @@
             }
         }
 
-        Sdk.getCurrent().setProject(project, (IAndroidTarget) parameters.get(PARAM_SDK_TARGET),
-                null /* apkConfigMap*/);
+        Sdk.getCurrent().setProject(project, target, null /* apkConfigMap*/);
 
         // Fix the project to make sure all properties are as expected.
         // Necessary for existing projects and good for new ones to.
@@ -839,23 +860,58 @@
      * Adds default application icon to the project.
      *
      * @param project The Java Project to update.
+     * @param legacy whether we're running in legacy mode (no density support)
      * @param monitor An existing monitor.
      * @throws CoreException if the method fails to update the project.
      */
-    private void addIcon(IProject project, IProgressMonitor monitor)
+    private void addIcon(IProject project, boolean legacy, IProgressMonitor monitor)
             throws CoreException {
-        IFile file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
-                                     + DRAWABLE_DIRECTORY + AndroidConstants.WS_SEP + ICON);
-        if (!file.exists()) {
-            // read the content from the template
-            byte[] buffer = AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON);
-
-            // if valid
-            if (buffer != null) {
-                // Save in the project
-                InputStream stream = new ByteArrayInputStream(buffer);
-                file.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
+        if (legacy) { // density support
+            // do medium density icon only, in the default drawable folder.
+            IFile file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+                    + DRAWABLE_DIRECTORY + AndroidConstants.WS_SEP + PROJECT_ICON);
+            if (!file.exists()) {
+                addFile(file, AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON_MDPI), monitor);
             }
+        } else {
+            // do all 3 icons.
+            IFile file;
+
+            // high density
+            file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+                    + DRAWABLE_HDPI_DIRECTORY + AndroidConstants.WS_SEP + PROJECT_ICON);
+            if (!file.exists()) {
+                addFile(file, AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON_HDPI), monitor);
+            }
+
+            // medium density
+            file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+                    + DRAWABLE_MDPI_DIRECTORY + AndroidConstants.WS_SEP + PROJECT_ICON);
+            if (!file.exists()) {
+                addFile(file, AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON_MDPI), monitor);
+            }
+
+            // low density
+            file = project.getFile(RES_DIRECTORY + AndroidConstants.WS_SEP
+                    + DRAWABLE_LDPI_DIRECTORY + AndroidConstants.WS_SEP + PROJECT_ICON);
+            if (!file.exists()) {
+                addFile(file, AdtPlugin.readEmbeddedFile(TEMPLATES_DIRECTORY + ICON_LDPI), monitor);
+            }
+        }
+    }
+
+    /**
+     * Creates a file from a data source.
+     * @param dest the file to write
+     * @param source the content of the file.
+     * @param monitor the progress monitor
+     * @throws CoreException
+     */
+    private void addFile(IFile dest, byte[] source, IProgressMonitor monitor) throws CoreException {
+        if (source != null) {
+            // Save in the project
+            InputStream stream = new ByteArrayInputStream(source);
+            dest.create(stream, false /* force */, new SubProgressMonitor(monitor, 10));
         }
     }
 
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon.png
deleted file mode 100644
index 7502484..0000000
--- a/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon.png
+++ /dev/null
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_hdpi.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_hdpi.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_hdpi.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_ldpi.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_ldpi.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_ldpi.png
Binary files differ
diff --git a/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_mdpi.png b/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_mdpi.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/tools/eclipse/plugins/com.android.ide.eclipse.adt/templates/icon_mdpi.png
Binary files differ
diff --git a/tools/scripts/AndroidManifest.template b/tools/scripts/AndroidManifest.template
index 9b07072..f14f147 100644
--- a/tools/scripts/AndroidManifest.template
+++ b/tools/scripts/AndroidManifest.template
@@ -3,7 +3,7 @@
       package="PACKAGE"
       android:versionCode="1"
       android:versionName="1.0">
-    <application android:label="@string/app_name">
+    <application android:label="@string/app_name" ICON>
         <activity android:name="ACTIVITY_ENTRY_NAME"
                   android:label="@string/app_name">
             <intent-filter>
diff --git a/tools/scripts/icon_hdpi.png b/tools/scripts/icon_hdpi.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/tools/scripts/icon_hdpi.png
Binary files differ
diff --git a/tools/scripts/icon_ldpi.png b/tools/scripts/icon_ldpi.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/tools/scripts/icon_ldpi.png
Binary files differ
diff --git a/tools/scripts/icon_mdpi.png b/tools/scripts/icon_mdpi.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/tools/scripts/icon_mdpi.png
Binary files differ
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
index 6394795..e9e5999 100644
--- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
+++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/project/ProjectCreator.java
@@ -29,6 +29,9 @@
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -66,6 +69,8 @@
     private final static String PH_ACTIVITY_TESTED_CLASS_NAME = "ACTIVITY_TESTED_CLASS_NAME";
     /** Project name substitution string used in template files, i.e. "PROJECT_NAME". */
     private final static String PH_PROJECT_NAME = "PROJECT_NAME";
+    /** Application icon substitution string used in the manifest template */
+    private final static String PH_ICON = "ICON";
 
     /** Pattern for characters accepted in a project name. Since this will be used as a
      * directory name, we're being a bit conservative on purpose: dot and space cannot be used. */
@@ -106,6 +111,7 @@
         /** default UID. This will not be serialized anyway. */
         private static final long serialVersionUID = 1L;
 
+        @SuppressWarnings("unused")
         ProjectCreateException(String message) {
             super(message);
         }
@@ -329,19 +335,26 @@
             }
 
             // create other useful folders
-            File resourceFodler = createDirs(projectFolder, SdkConstants.FD_RESOURCES);
+            File resourceFolder = createDirs(projectFolder, SdkConstants.FD_RESOURCES);
             createDirs(projectFolder, SdkConstants.FD_OUTPUT);
             createDirs(projectFolder, SdkConstants.FD_NATIVE_LIBS);
 
             if (isTestProject == false) {
                 /* Make res files only for non test projects */
-                File valueFolder = createDirs(resourceFodler, SdkConstants.FD_VALUES);
+                File valueFolder = createDirs(resourceFolder, SdkConstants.FD_VALUES);
                 installTemplate("strings.template", new File(valueFolder, "strings.xml"),
                         keywords, target);
 
-                File layoutFolder = createDirs(resourceFodler, SdkConstants.FD_LAYOUT);
+                File layoutFolder = createDirs(resourceFolder, SdkConstants.FD_LAYOUT);
                 installTemplate("layout.template", new File(layoutFolder, "main.xml"),
                         keywords, target);
+
+                // create the icons
+                if (installIcons(resourceFolder, target)) {
+                    keywords.put(PH_ICON, "android:icon=\"@drawable/icon\"");
+                } else {
+                    keywords.put(PH_ICON, "");
+                }
             }
 
             /* Make AndroidManifest.xml and build.xml files */
@@ -776,8 +789,10 @@
             String line;
 
             while ((line = in.readLine()) != null) {
-                for (String key : placeholderMap.keySet()) {
-                    line = line.replace(key, placeholderMap.get(key));
+                if (placeholderMap != null) {
+                    for (String key : placeholderMap.keySet()) {
+                        line = line.replace(key, placeholderMap.get(key));
+                    }
                 }
 
                 out.write(line);
@@ -797,6 +812,85 @@
     }
 
     /**
+     * Installs the project icons.
+     * @param resourceFolder the resource folder
+     * @param target the target of the project.
+     * @return true if any icon was installed.
+     */
+    private boolean installIcons(File resourceFolder, IAndroidTarget target)
+            throws ProjectCreateException {
+        // query the target for its template directory
+        String templateFolder = target.getPath(IAndroidTarget.TEMPLATES);
+
+        boolean installedIcon = false;
+
+        installedIcon |= installIcon(templateFolder, "icon_hdpi.png", resourceFolder, "drawable-hdpi");
+        installedIcon |= installIcon(templateFolder, "icon_mdpi.png", resourceFolder, "drawable-mdpi");
+        installedIcon |= installIcon(templateFolder, "icon_ldpi.png", resourceFolder, "drawable-ldpi");
+
+        return installedIcon;
+    }
+
+    /**
+     * Installs an Icon in the project.
+     * @return true if the icon was installed.
+     */
+    private boolean installIcon(String templateFolder, String iconName, File resourceFolder,
+            String folderName) throws ProjectCreateException {
+        File icon = new File(templateFolder, iconName);
+        if (icon.exists()) {
+            File drawable = createDirs(resourceFolder, folderName);
+            installBinaryFile(icon, new File(drawable, "icon.png"));
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Installs a binary file
+     * @param source the source file to copy
+     * @param destination the destination file to write
+     */
+    private void installBinaryFile(File source, File destination) {
+        byte[] buffer = new byte[8192];
+
+        FileInputStream fis = null;
+        FileOutputStream fos = null;
+        try {
+            fis = new FileInputStream(source);
+            fos = new FileOutputStream(destination);
+
+            int read;
+            while ((read = fis.read(buffer)) != -1) {
+                fos.write(buffer, 0, read);
+            }
+
+        } catch (FileNotFoundException e) {
+            // shouldn't happen since we check before.
+        } catch (IOException e) {
+            new ProjectCreateException(e, "Failed to read binary file: %1$s",
+                    source.getAbsolutePath());
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+            if (fos != null) {
+                try {
+                    fos.close();
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+        }
+        
+    }
+
+    /**
      * Prints a message unless silence is enabled.
      * <p/>
      * This is just a convenience wrapper around {@link ISdkLog#printf(String, Object...)} from