diff --git a/tools/droiddoc/src/DroidDoc.java b/tools/droiddoc/src/DroidDoc.java
new file mode 100644
index 0000000..f664c41
--- /dev/null
+++ b/tools/droiddoc/src/DroidDoc.java
@@ -0,0 +1,1342 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import com.sun.javadoc.*;
+
+import org.clearsilver.HDF;
+
+import java.util.*;
+import java.io.*;
+import java.lang.reflect.Proxy;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class DroidDoc
+{
+    private static final String SDK_CONSTANT_ANNOTATION = "android.annotation.SdkConstant";
+    private static final String SDK_CONSTANT_TYPE_ACTIVITY_ACTION = "android.annotation.SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION";
+    private static final String SDK_CONSTANT_TYPE_BROADCAST_ACTION = "android.annotation.SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION";
+    private static final String SDK_CONSTANT_TYPE_SERVICE_ACTION = "android.annotation.SdkConstant.SdkConstantType.SERVICE_INTENT_ACTION";
+    private static final String SDK_CONSTANT_TYPE_CATEGORY = "android.annotation.SdkConstant.SdkConstantType.INTENT_CATEGORY";
+    private static final String SDK_WIDGET_ANNOTATION = "android.annotation.Widget";
+    private static final String SDK_LAYOUT_ANNOTATION = "android.annotation.Layout";
+
+    private static final int TYPE_NONE = 0;
+    private static final int TYPE_WIDGET = 1;
+    private static final int TYPE_LAYOUT = 2;
+    private static final int TYPE_LAYOUT_PARAM = 3;
+    
+    public static final int SHOW_PUBLIC = 0x00000001;
+    public static final int SHOW_PROTECTED = 0x00000003;
+    public static final int SHOW_PACKAGE = 0x00000007;
+    public static final int SHOW_PRIVATE = 0x0000000f;
+    public static final int SHOW_HIDDEN = 0x0000001f;
+
+    public static int showLevel = SHOW_PROTECTED;
+
+    public static final String javadocDir = "reference/";
+    public static String htmlExtension;
+
+    public static RootDoc root;
+    public static ArrayList<String[]> mHDFData = new ArrayList<String[]>();
+    public static Map<Character,String> escapeChars = new HashMap<Character,String>();
+    public static String title = "";
+
+    public static boolean checkLevel(int level)
+    {
+        return (showLevel & level) == level;
+    }
+
+    public static boolean checkLevel(boolean pub, boolean prot, boolean pkgp,
+            boolean priv, boolean hidden)
+    {
+        int level = 0;
+        if (hidden && !checkLevel(SHOW_HIDDEN)) {
+            return false;
+        }
+        if (pub && checkLevel(SHOW_PUBLIC)) {
+            return true;
+        }
+        if (prot && checkLevel(SHOW_PROTECTED)) {
+            return true;
+        }
+        if (pkgp && checkLevel(SHOW_PACKAGE)) {
+            return true;
+        }
+        if (priv && checkLevel(SHOW_PRIVATE)) {
+            return true;
+        }
+        return false;
+    }
+    
+    public static boolean start(RootDoc r)
+    {
+        String keepListFile = null;
+        String proofreadFile = null;
+        String todoFile = null;
+        String sdkValuePath = null;
+        ArrayList<SampleCode> sampleCodes = new ArrayList<SampleCode>();
+        String stubsDir = null;
+        //Create the dependency graph for the stubs directory
+        boolean apiXML = false;
+        String apiFile = null;
+        String debugStubsFile = "";
+        HashSet<String> stubPackages = null;
+
+        root = r;
+
+        String[][] options = r.options();
+        for (String[] a: options) {
+            if (a[0].equals("-d")) {
+                ClearPage.outputDir = a[1];
+            }
+            else if (a[0].equals("-templatedir")) {
+                ClearPage.addTemplateDir(a[1]);
+            }
+            else if (a[0].equals("-hdf")) {
+                mHDFData.add(new String[] {a[1], a[2]});
+            }
+            else if (a[0].equals("-toroot")) {
+                ClearPage.toroot = a[1];
+            }
+            else if (a[0].equals("-samplecode")) {
+                sampleCodes.add(new SampleCode(a[1], a[2], a[3]));
+            }
+            else if (a[0].equals("-htmldir")) {
+                ClearPage.htmlDir = a[1];
+            }
+            else if (a[0].equals("-title")) {
+                DroidDoc.title = a[1];
+            }
+            else if (a[0].equals("-werror")) {
+                Errors.setWarningsAreErrors(true);
+            }
+            else if (a[0].equals("-error") || a[0].equals("-warning")
+                    || a[0].equals("-hide")) {
+                try {
+                    int level = -1;
+                    if (a[0].equals("-error")) {
+                        level = Errors.ERROR;
+                    }
+                    else if (a[0].equals("-warning")) {
+                        level = Errors.WARNING;
+                    }
+                    else if (a[0].equals("-hide")) {
+                        level = Errors.HIDDEN;
+                    }
+                    Errors.setErrorLevel(Integer.parseInt(a[1]), level);
+                }
+                catch (NumberFormatException e) {
+                    // already printed below
+                    return false;
+                }
+            }
+            else if (a[0].equals("-keeplist")) {
+                keepListFile = a[1];
+            }
+            else if (a[0].equals("-proofread")) {
+                proofreadFile = a[1];
+            }
+            else if (a[0].equals("-todo")) {
+                todoFile = a[1];
+            }
+            else if (a[0].equals("-public")) {
+                showLevel = SHOW_PUBLIC;
+            }
+            else if (a[0].equals("-protected")) {
+                showLevel = SHOW_PROTECTED;
+            }
+            else if (a[0].equals("-package")) {
+                showLevel = SHOW_PACKAGE;
+            }
+            else if (a[0].equals("-private")) {
+                showLevel = SHOW_PRIVATE;
+            }
+            else if (a[0].equals("-hidden")) {
+                showLevel = SHOW_HIDDEN;
+            }
+            else if (a[0].equals("-stubs")) {
+                stubsDir = a[1];
+            }
+            else if (a[0].equals("-stubpackages")) {
+                stubPackages = new HashSet();
+                for (String pkg: a[1].split(":")) {
+                    stubPackages.add(pkg);
+                }
+            }
+            else if (a[0].equals("-sdkvalues")) {
+                sdkValuePath = a[1];
+            }
+            else if (a[0].equals("-apixml")) {
+                apiXML = true;
+                apiFile = a[1];
+            }
+        }
+
+        // read some prefs from the template
+        if (!readTemplateSettings()) {
+            return false;
+        }
+
+        // Set up the data structures
+        Converter.makeInfo(r);
+
+        // Files for proofreading
+        if (proofreadFile != null) {
+            Proofread.initProofread(proofreadFile);
+        }
+        if (todoFile != null) {
+            TodoFile.writeTodoFile(todoFile);
+        }
+
+        // HTML Pages
+        if (ClearPage.htmlDir != null) {
+            writeHTMLPages();
+        }
+
+        // Navigation tree
+        NavTree.writeNavTree(javadocDir);
+
+        // Packages Pages
+        writePackages(javadocDir
+                        + (ClearPage.htmlDir!=null
+                            ? "packages" + htmlExtension
+                            : "index" + htmlExtension));
+
+        // Classes
+        writeClassLists();
+        writeClasses();
+        writeHierarchy();
+ //      writeKeywords();
+
+        // Lists for JavaScript
+        writeLists();
+        if (keepListFile != null) {
+            writeKeepList(keepListFile);
+        }
+
+        // Sample Code
+        for (SampleCode sc: sampleCodes) {
+            sc.write();
+        }
+
+        // Index page
+        writeIndex();
+
+        Proofread.finishProofread(proofreadFile);
+
+        // Stubs
+        if (stubsDir != null) {
+            Stubs.writeStubs(stubsDir, apiXML, apiFile, stubPackages);
+        }
+        
+        if (sdkValuePath != null) {
+            writeSdkValues(sdkValuePath);
+        }
+
+        Errors.printErrors();
+        return !Errors.hadError;
+    }
+
+    private static void writeIndex() {
+        HDF data = makeHDF();
+        ClearPage.write(data, "index.cs", javadocDir + "index" + htmlExtension);
+    }
+
+    private static boolean readTemplateSettings()
+    {
+        HDF data = makeHDF();
+        htmlExtension = data.getValue("template.extension", ".html");
+        int i=0;
+        while (true) {
+            String k = data.getValue("template.escape." + i + ".key", "");
+            String v = data.getValue("template.escape." + i + ".value", "");
+            if ("".equals(k)) {
+                break;
+            }
+            if (k.length() != 1) {
+                System.err.println("template.escape." + i + ".key must have a length of 1: " + k);
+                return false;
+            }
+            escapeChars.put(k.charAt(0), v);
+            i++;
+        }
+        return true;
+    }
+
+    public static String escape(String s) {
+        if (escapeChars.size() == 0) {
+            return s;
+        }
+        StringBuffer b = null;
+        int begin = 0;
+        final int N = s.length();
+        for (int i=0; i<N; i++) {
+            char c = s.charAt(i);
+            String mapped = escapeChars.get(c);
+            if (mapped != null) {
+                if (b == null) {
+                    b = new StringBuffer(s.length() + mapped.length());
+                }
+                if (begin != i) {
+                    b.append(s.substring(begin, i));
+                }
+                b.append(mapped);
+                begin = i+1;
+            }
+        }
+        if (b != null) {
+            if (begin != N) {
+                b.append(s.substring(begin, N));
+            }
+            return b.toString();
+        }
+        return s;
+    }
+
+    public static void setPageTitle(HDF data, String title)
+    {
+        String s = title;
+        if (DroidDoc.title.length() > 0) {
+            s += " - " + DroidDoc.title;
+        }
+        data.setValue("page.title", s);
+    }
+
+    public static LanguageVersion languageVersion()
+    {
+        return LanguageVersion.JAVA_1_5;
+    }
+
+    public static int optionLength(String option)
+    {
+        if (option.equals("-d")) {
+            return 2;
+        }
+        if (option.equals("-templatedir")) {
+            return 2;
+        }
+        if (option.equals("-hdf")) {
+            return 3;
+        }
+        if (option.equals("-toroot")) {
+            return 2;
+        }
+        if (option.equals("-samplecode")) {
+            return 4;
+        }
+        if (option.equals("-htmldir")) {
+            return 2;
+        }
+        if (option.equals("-title")) {
+            return 2;
+        }
+        if (option.equals("-werror")) {
+            return 1;
+        }
+        if (option.equals("-hide")) {
+            return 2;
+        }
+        if (option.equals("-warning")) {
+            return 2;
+        }
+        if (option.equals("-error")) {
+            return 2;
+        }
+        if (option.equals("-keeplist")) {
+            return 2;
+        }
+        if (option.equals("-proofread")) {
+            return 2;
+        }
+        if (option.equals("-todo")) {
+            return 2;
+        }
+        if (option.equals("-public")) {
+            return 1;
+        }
+        if (option.equals("-protected")) {
+            return 1;
+        }
+        if (option.equals("-package")) {
+            return 1;
+        }
+        if (option.equals("-private")) {
+            return 1;
+        }
+        if (option.equals("-hidden")) {
+            return 1;
+        }
+        if (option.equals("-stubs")) {
+            return 2;
+        }
+        if (option.equals("-stubpackages")) {
+            return 2;
+        }
+        if (option.equals("-sdkvalues")) {
+            return 2;
+        }
+        if (option.equals("-apixml")) {
+            return 2;
+        }
+        return 0;
+    }
+    
+    public static boolean validOptions(String[][] options, DocErrorReporter r)
+    {
+        for (String[] a: options) {
+            if (a[0].equals("-error") || a[0].equals("-warning")
+                    || a[0].equals("-hide")) {
+                try {
+                    Integer.parseInt(a[1]);
+                }
+                catch (NumberFormatException e) {
+                    r.printError("bad -" + a[0] + " value must be a number: "
+                            + a[1]);
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+    public static HDF makeHDF()
+    {
+        HDF data = new HDF();
+
+        for (String[] p: mHDFData) {
+            data.setValue(p[0], p[1]);
+        }
+
+        try {
+            for (String p: ClearPage.hdfFiles) {
+                data.readFile(p);
+            }
+        }
+        catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return data;
+    }
+
+    public static HDF makePackageHDF()
+    {
+        HDF data = makeHDF();
+        ClassInfo[] classes = Converter.rootClasses();
+
+        SortedMap<String, PackageInfo> sorted = new TreeMap<String, PackageInfo>();
+        for (ClassInfo cl: classes) {
+            PackageInfo pkg = cl.containingPackage();
+            String name;
+            if (pkg == null) {
+                name = "";
+            } else {
+                name = pkg.name();
+            }
+            sorted.put(name, pkg);
+        }
+
+        int i = 0;
+        for (String s: sorted.keySet()) {
+            PackageInfo pkg = sorted.get(s);
+
+            if (pkg.isHidden()) {
+                continue;
+            }
+            Boolean allHidden = true;
+            int pass = 0;
+            ClassInfo[] classesToCheck = null;
+            while (pass < 5 ) {
+                switch(pass) {
+                case 0:
+                    classesToCheck = pkg.ordinaryClasses();
+                    break;
+                case 1:
+                    classesToCheck = pkg.enums();
+                    break;
+                case 2:
+                    classesToCheck = pkg.errors();
+                    break;
+                case 3:
+                    classesToCheck = pkg.exceptions();
+                    break;
+                case 4:
+                    classesToCheck = pkg.interfaces();
+                    break;
+                default:
+                    System.err.println("Error reading package: " + pkg.name());
+                    break;
+                }
+                for (ClassInfo cl : classesToCheck) {
+                    if (!cl.isHidden()) {
+                        allHidden = false;
+                        break;
+                    }
+                }
+                if (!allHidden) {
+                    break;
+                }
+                pass++;
+            }
+            if (allHidden) {
+                continue;
+            }
+
+            data.setValue("reference", "true");
+            data.setValue("docs.packages." + i + ".name", s);
+            data.setValue("docs.packages." + i + ".link", pkg.htmlPage());
+            TagInfo.makeHDF(data, "docs.packages." + i + ".shortDescr",
+                                               pkg.firstSentenceTags());
+            i++;
+        }
+
+        return data;
+    }
+
+    public static void writeDirectory(File dir, String relative)
+    {
+        File[] files = dir.listFiles();
+        int i, count = files.length;
+        for (i=0; i<count; i++) {
+            File f = files[i];
+            if (f.isFile()) {
+                String templ = relative + f.getName();
+                int len = templ.length();
+                if (len > 3 && ".cs".equals(templ.substring(len-3))) {
+                    HDF data = makeHDF();
+                    String filename = templ.substring(0,len-3) + htmlExtension;
+                    ClearPage.write(data, templ, filename);
+                }
+                else if (len > 3 && ".jd".equals(templ.substring(len-3))) {
+                    String filename = templ.substring(0,len-3) + htmlExtension;
+                    DocFile.writePage(f.getAbsolutePath(), relative, filename);
+                }
+                else {
+                    ClearPage.copyFile(f, templ);
+                }
+            }
+            else if (f.isDirectory()) {
+                writeDirectory(f, relative + f.getName() + "/");
+            }
+        }
+    }
+
+    public static void writeHTMLPages()
+    {
+        File f = new File(ClearPage.htmlDir);
+        if (!f.isDirectory()) {
+            System.err.println("htmlDir not a directory: " + ClearPage.htmlDir);
+        }
+        writeDirectory(f, "");
+    }
+
+    public static void writeLists()
+    {
+        HDF data = makeHDF();
+
+        ClassInfo[] classes = Converter.rootClasses();
+
+        SortedMap<String, Object> sorted = new TreeMap<String, Object>();
+        for (ClassInfo cl: classes) {
+            if (cl.isHidden()) {
+                continue;
+            }
+            sorted.put(cl.qualifiedName(), cl);
+            PackageInfo pkg = cl.containingPackage();
+            String name;
+            if (pkg == null) {
+                name = "";
+            } else {
+                name = pkg.name();
+            }
+            sorted.put(name, pkg);
+        }
+
+        int i = 0;
+        for (String s: sorted.keySet()) {
+            data.setValue("docs.pages." + i + ".id" , ""+i);
+            data.setValue("docs.pages." + i + ".label" , s);
+
+            Object o = sorted.get(s);
+            if (o instanceof PackageInfo) {
+                PackageInfo pkg = (PackageInfo)o;
+                data.setValue("docs.pages." + i + ".link" , pkg.htmlPage());
+                data.setValue("docs.pages." + i + ".type" , "package");
+            }
+            else if (o instanceof ClassInfo) {
+                ClassInfo cl = (ClassInfo)o;
+                data.setValue("docs.pages." + i + ".link" , cl.htmlPage());
+                data.setValue("docs.pages." + i + ".type" , "class");
+            }
+            i++;
+        }
+
+        ClearPage.write(data, "lists.cs", javadocDir + "lists.js");
+    }
+
+    public static void cantStripThis(ClassInfo cl, HashSet<ClassInfo> notStrippable) {
+        if (!notStrippable.add(cl)) {
+            // slight optimization: if it already contains cl, it already contains
+            // all of cl's parents
+            return;
+        }
+        ClassInfo supr = cl.superclass();
+        if (supr != null) {
+            cantStripThis(supr, notStrippable);
+        }
+        for (ClassInfo iface: cl.interfaces()) {
+            cantStripThis(iface, notStrippable);
+        }
+    }
+
+    private static String getPrintableName(ClassInfo cl) {
+        ClassInfo containingClass = cl.containingClass();
+        if (containingClass != null) {
+            // This is an inner class.
+            String baseName = cl.name();
+            baseName = baseName.substring(baseName.lastIndexOf('.') + 1);
+            return getPrintableName(containingClass) + '$' + baseName;
+        }
+        return cl.qualifiedName();
+    }
+
+    /**
+     * Writes the list of classes that must be present in order to
+     * provide the non-hidden APIs known to javadoc.
+     *
+     * @param filename the path to the file to write the list to
+     */
+    public static void writeKeepList(String filename) {
+        HashSet<ClassInfo> notStrippable = new HashSet<ClassInfo>();
+        ClassInfo[] all = Converter.allClasses();
+        Arrays.sort(all); // just to make the file a little more readable
+
+        // If a class is public and not hidden, then it and everything it derives
+        // from cannot be stripped.  Otherwise we can strip it.
+        for (ClassInfo cl: all) {
+            if (cl.isPublic() && !cl.isHidden()) {
+                cantStripThis(cl, notStrippable);
+            }
+        }
+        PrintStream stream = null;
+        try {
+            stream = new PrintStream(filename);
+            for (ClassInfo cl: notStrippable) {
+                stream.println(getPrintableName(cl));
+            }
+        }
+        catch (FileNotFoundException e) {
+            System.err.println("error writing file: " + filename);
+        }
+        finally {
+            if (stream != null) {
+                stream.close();
+            }
+        }
+    }
+
+    private static PackageInfo[] sVisiblePackages = null;
+    public static PackageInfo[] choosePackages() {
+        if (sVisiblePackages != null) {
+            return sVisiblePackages;
+        }
+
+        ClassInfo[] classes = Converter.rootClasses();
+        SortedMap<String, PackageInfo> sorted = new TreeMap<String, PackageInfo>();
+        for (ClassInfo cl: classes) {
+            PackageInfo pkg = cl.containingPackage();
+            String name;
+            if (pkg == null) {
+                name = "";
+            } else {
+                name = pkg.name();
+            }
+            sorted.put(name, pkg);
+        }
+
+        ArrayList<PackageInfo> result = new ArrayList();
+
+        for (String s: sorted.keySet()) {
+            PackageInfo pkg = sorted.get(s);
+
+            if (pkg.isHidden()) {
+                continue;
+            }
+            Boolean allHidden = true;
+            int pass = 0;
+            ClassInfo[] classesToCheck = null;
+            while (pass < 5 ) {
+                switch(pass) {
+                case 0:
+                    classesToCheck = pkg.ordinaryClasses();
+                    break;
+                case 1:
+                    classesToCheck = pkg.enums();
+                    break;
+                case 2:
+                    classesToCheck = pkg.errors();
+                    break;
+                case 3:
+                    classesToCheck = pkg.exceptions();
+                    break;
+                case 4:
+                    classesToCheck = pkg.interfaces();
+                    break;
+                default:
+                    System.err.println("Error reading package: " + pkg.name());
+                    break;
+                }
+                for (ClassInfo cl : classesToCheck) {
+                    if (!cl.isHidden()) {
+                        allHidden = false;
+                        break;
+                    }
+                }
+                if (!allHidden) {
+                    break;
+                }
+                pass++;
+            }
+            if (allHidden) {
+                continue;
+            }
+
+            result.add(pkg);
+        }
+
+        sVisiblePackages = result.toArray(new PackageInfo[result.size()]);
+        return sVisiblePackages;
+    }
+
+    public static void writePackages(String filename)
+    {
+        HDF data = makePackageHDF();
+
+        int i = 0;
+        for (PackageInfo pkg: choosePackages()) {
+            writePackage(pkg);
+
+            data.setValue("docs.packages." + i + ".name", pkg.name());
+            data.setValue("docs.packages." + i + ".link", pkg.htmlPage());
+            TagInfo.makeHDF(data, "docs.packages." + i + ".shortDescr",
+                            pkg.firstSentenceTags());
+
+            i++;
+        }
+
+        setPageTitle(data, "Package Index");
+
+        TagInfo.makeHDF(data, "root.descr",
+                Converter.convertTags(root.inlineTags(), null));
+
+        ClearPage.write(data, "packages.cs", filename);
+        ClearPage.write(data, "package-list.cs", javadocDir + "package-list");
+
+        Proofread.writePackages(filename,
+                Converter.convertTags(root.inlineTags(), null));
+    }
+
+    public static void writePackage(PackageInfo pkg)
+    {
+        // these this and the description are in the same directory,
+        // so it's okay
+        HDF data = makePackageHDF();
+
+        String name = pkg.name();
+
+        data.setValue("package.name", name);
+        data.setValue("package.descr", "...description...");
+
+        makeClassListHDF(data, "package.interfaces", 
+                         ClassInfo.sortByName(pkg.interfaces()));
+        makeClassListHDF(data, "package.classes",
+                         ClassInfo.sortByName(pkg.ordinaryClasses()));
+        makeClassListHDF(data, "package.enums",
+                         ClassInfo.sortByName(pkg.enums()));
+        makeClassListHDF(data, "package.exceptions",
+                         ClassInfo.sortByName(pkg.exceptions()));
+        makeClassListHDF(data, "package.errors",
+                         ClassInfo.sortByName(pkg.errors()));
+        TagInfo.makeHDF(data, "package.shortDescr",
+                         pkg.firstSentenceTags());
+        TagInfo.makeHDF(data, "package.descr", pkg.inlineTags());
+
+        String filename = pkg.htmlPage();
+        setPageTitle(data, name);
+        ClearPage.write(data, "package.cs", filename);
+
+        filename = pkg.fullDescriptionHtmlPage();
+        setPageTitle(data, name + " Details");
+        ClearPage.write(data, "package-descr.cs", filename);
+
+        Proofread.writePackage(filename, pkg.inlineTags());
+    }
+
+    public static void writeClassLists()
+    {
+        int i;
+        HDF data = makePackageHDF();
+
+        ClassInfo[] classes = PackageInfo.filterHidden(
+                                    Converter.convertClasses(root.classes()));
+        if (classes.length == 0) {
+            return ;
+        }
+
+        Sorter[] sorted = new Sorter[classes.length];
+        for (i=0; i<sorted.length; i++) {
+            ClassInfo cl = classes[i];
+            String name = cl.name();
+            sorted[i] = new Sorter(name, cl);
+        }
+
+        Arrays.sort(sorted);
+
+        // make a pass and resolve ones that have the same name
+        int firstMatch = 0;
+        String lastName = sorted[0].label;
+        for (i=1; i<sorted.length; i++) {
+            String s = sorted[i].label;
+            if (!lastName.equals(s)) {
+                if (firstMatch != i-1) {
+                    // there were duplicates
+                    for (int j=firstMatch; j<i; j++) {
+                        PackageInfo pkg = ((ClassInfo)sorted[j].data).containingPackage();
+                        if (pkg != null) {
+                            sorted[j].label = sorted[j].label + " (" + pkg.name() + ")";
+                        }
+                    }
+                }
+                firstMatch = i;
+                lastName = s;
+            }
+        }
+
+        // and sort again
+        Arrays.sort(sorted);
+
+        for (i=0; i<sorted.length; i++) {
+            String s = sorted[i].label;
+            ClassInfo cl = (ClassInfo)sorted[i].data;
+            char first = Character.toUpperCase(s.charAt(0));
+            cl.makeShortDescrHDF(data, "docs.classes." + first + '.' + i);
+        }
+
+        setPageTitle(data, "Class Index");
+        ClearPage.write(data, "classes.cs", javadocDir + "classes" + htmlExtension);
+    }
+
+    // we use the word keywords because "index" means something else in html land
+    // the user only ever sees the word index
+/*    public static void writeKeywords()
+    {
+        ArrayList<KeywordEntry> keywords = new ArrayList<KeywordEntry>();
+
+        ClassInfo[] classes = PackageInfo.filterHidden(Converter.convertClasses(root.classes()));
+
+        for (ClassInfo cl: classes) {
+            cl.makeKeywordEntries(keywords);
+        }
+
+        HDF data = makeHDF();
+
+        Collections.sort(keywords);
+        
+        int i=0;
+        for (KeywordEntry entry: keywords) {
+            String base = "keywords." + entry.firstChar() + "." + i;
+            entry.makeHDF(data, base);
+            i++;
+        }
+
+        setPageTitle(data, "Index");
+        ClearPage.write(data, "keywords.cs", javadocDir + "keywords" + htmlExtension);
+    } */
+
+    public static void writeHierarchy()
+    {
+        ClassInfo[] classes = Converter.rootClasses();
+        ArrayList<ClassInfo> info = new ArrayList<ClassInfo>();
+        for (ClassInfo cl: classes) {
+            if (!cl.isHidden()) {
+                info.add(cl);
+            }
+        }
+        HDF data = makePackageHDF();
+        Hierarchy.makeHierarchy(data, info.toArray(new ClassInfo[info.size()]));
+        setPageTitle(data, "Class Hierarchy");
+        ClearPage.write(data, "hierarchy.cs", javadocDir + "hierarchy" + htmlExtension);
+    }
+
+    public static void writeClasses()
+    {
+        ClassInfo[] classes = Converter.rootClasses();
+
+        for (ClassInfo cl: classes) {
+            HDF data = makePackageHDF();
+            if (!cl.isHidden()) {
+                writeClass(cl, data);
+            }
+        }
+    }
+
+    public static void writeClass(ClassInfo cl, HDF data)
+    {
+        cl.makeHDF(data);
+
+        setPageTitle(data, cl.name());
+        ClearPage.write(data, "class.cs", cl.htmlPage());
+
+        Proofread.writeClass(cl.htmlPage(), cl);
+    }
+
+    public static void makeClassListHDF(HDF data, String base,
+            ClassInfo[] classes)
+    {
+        for (int i=0; i<classes.length; i++) {
+            ClassInfo cl = classes[i];
+            if (!cl.isHidden()) {
+                cl.makeShortDescrHDF(data, base + "." + i);
+            }
+        }
+    }
+
+    public static String linkTarget(String source, String target)
+    {
+        String[] src = source.split("/");
+        String[] tgt = target.split("/");
+
+        int srclen = src.length;
+        int tgtlen = tgt.length;
+
+        int same = 0;
+        while (same < (srclen-1)
+                && same < (tgtlen-1)
+                && (src[same].equals(tgt[same]))) {
+            same++;
+        }
+
+        String s = "";
+
+        int up = srclen-same-1;
+        for (int i=0; i<up; i++) {
+            s += "../";
+        }
+
+
+        int N = tgtlen-1;
+        for (int i=same; i<N; i++) {
+            s += tgt[i] + '/';
+        }
+        s += tgt[tgtlen-1];
+
+        return s;
+    }
+
+    /**
+     * Returns true if the given element has an @hide annotation.
+     */
+    private static boolean hasHideAnnotation(Doc doc) {
+        return doc.getRawCommentText().indexOf("@hide") != -1;
+    }
+
+    /**
+     * Returns true if the given element is hidden.
+     */
+    private static boolean isHidden(Doc doc) {
+        // Methods, fields, constructors.
+        if (doc instanceof MemberDoc) {
+            return hasHideAnnotation(doc);
+        }
+
+        // Classes, interfaces, enums, annotation types.
+        if (doc instanceof ClassDoc) {
+            ClassDoc classDoc = (ClassDoc) doc;
+
+            // Check the containing package.
+            if (hasHideAnnotation(classDoc.containingPackage())) {
+                return true;
+            }
+
+            // Check the class doc and containing class docs if this is a
+            // nested class.
+            ClassDoc current = classDoc;
+            do {
+                if (hasHideAnnotation(current)) {
+                    return true;
+                }
+
+                current = current.containingClass();
+            } while (current != null);
+        }
+
+        return false;
+    }
+
+    /**
+     * Filters out hidden elements.
+     */
+    private static Object filterHidden(Object o, Class<?> expected) {
+        if (o == null) {
+            return null;
+        }
+
+        Class type = o.getClass();
+        if (type.getName().startsWith("com.sun.")) {
+            // TODO: Implement interfaces from superclasses, too.
+            return Proxy.newProxyInstance(type.getClassLoader(),
+                    type.getInterfaces(), new HideHandler(o));
+        } else if (o instanceof Object[]) {
+            Class<?> componentType = expected.getComponentType();
+            Object[] array = (Object[]) o;
+            List<Object> list = new ArrayList<Object>(array.length);
+            for (Object entry : array) {
+                if ((entry instanceof Doc) && isHidden((Doc) entry)) {
+                    continue;
+                }
+                list.add(filterHidden(entry, componentType));
+            }
+            return list.toArray(
+                    (Object[]) Array.newInstance(componentType, list.size()));
+        } else {
+            return o;
+        }
+    }
+
+    /**
+     * Filters hidden elements out of method return values.
+     */
+    private static class HideHandler implements InvocationHandler {
+
+        private final Object target;
+
+        public HideHandler(Object target) {
+            this.target = target;
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args)
+                throws Throwable {
+            String methodName = method.getName();
+            if (args != null) {
+                if (methodName.equals("compareTo") ||
+                    methodName.equals("equals") ||
+                    methodName.equals("overrides") ||
+                    methodName.equals("subclassOf")) {
+                    args[0] = unwrap(args[0]);
+                }
+            }
+
+            if (methodName.equals("getRawCommentText")) {
+                return filterComment((String) method.invoke(target, args));
+            }
+            
+            // escape "&" in disjunctive types.
+            if (proxy instanceof Type && methodName.equals("toString")) {
+                return ((String) method.invoke(target, args))
+                        .replace("&", "&amp;");
+            }
+
+            try {
+                return filterHidden(method.invoke(target, args),
+                        method.getReturnType());
+            } catch (InvocationTargetException e) {
+                throw e.getTargetException();
+            }
+        }
+
+        private String filterComment(String s) {
+            if (s == null) {
+                return null;
+            }
+
+            s = s.trim();
+
+            // Work around off by one error
+            while (s.length() >= 5
+                    && s.charAt(s.length() - 5) == '{') {
+                s += "&nbsp;";
+            }
+
+            return s;
+        }
+
+        private static Object unwrap(Object proxy) {
+            if (proxy instanceof Proxy)
+                return ((HideHandler)Proxy.getInvocationHandler(proxy)).target;
+            return proxy;
+        }
+    }
+
+    public static String scope(Scoped scoped) {
+        if (scoped.isPublic()) {
+            return "public";
+        }
+        else if (scoped.isProtected()) {
+            return "protected";
+        }
+        else if (scoped.isPackagePrivate()) {
+            return "";
+        }
+        else if (scoped.isPrivate()) {
+            return "private";
+        }
+        else {
+            throw new RuntimeException("invalid scope for object " + scoped);
+        }
+    }
+    
+    /**
+     * Collect the values used by the Dev tools and write them in files packaged with the SDK
+     * @param output the ouput directory for the files.
+     */
+    private static void writeSdkValues(String output) {
+        ArrayList<String> activityActions = new ArrayList<String>();
+        ArrayList<String> broadcastActions = new ArrayList<String>();
+        ArrayList<String> serviceActions = new ArrayList<String>();
+        ArrayList<String> categories = new ArrayList<String>();
+        
+        ArrayList<ClassInfo> layouts = new ArrayList<ClassInfo>();
+        ArrayList<ClassInfo> widgets = new ArrayList<ClassInfo>();
+        ArrayList<ClassInfo> layoutParams = new ArrayList<ClassInfo>();
+        
+        ClassInfo[] classes = Converter.allClasses();
+
+        // Go through all the fields of all the classes, looking SDK stuff.
+        for (ClassInfo clazz : classes) {
+            
+            // first check constant fields for the SdkConstant annotation.
+            FieldInfo[] fields = clazz.allSelfFields();
+            for (FieldInfo field : fields) {
+                Object cValue = field.constantValue();
+                if (cValue != null) {
+                    AnnotationInstanceInfo[] annotations = field.annotations();
+                    if (annotations.length > 0) {
+                        for (AnnotationInstanceInfo annotation : annotations) {
+                            if (SDK_CONSTANT_ANNOTATION.equals(annotation.type().qualifiedName())) {
+                                AnnotationValueInfo[] values = annotation.elementValues();
+                                if (values.length > 0) {
+                                    String type = values[0].valueString();
+                                    if (SDK_CONSTANT_TYPE_ACTIVITY_ACTION.equals(type)) {
+                                        activityActions.add(cValue.toString());
+                                    } else if (SDK_CONSTANT_TYPE_BROADCAST_ACTION.equals(type)) {
+                                        broadcastActions.add(cValue.toString());
+                                    } else if (SDK_CONSTANT_TYPE_SERVICE_ACTION.equals(type)) {
+                                        serviceActions.add(cValue.toString());
+                                    } else if (SDK_CONSTANT_TYPE_CATEGORY.equals(type)) {
+                                        categories.add(cValue.toString());
+                                    }
+                                }
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+            
+            // Now check the class for @Widget or if its in the android.widget package
+            // (unless the class is hidden or abstract, or non public)
+            if (clazz.isHidden() == false && clazz.isPublic() && clazz.isAbstract() == false) {
+                boolean annotated = false;
+                AnnotationInstanceInfo[] annotations = clazz.annotations();
+                if (annotations.length > 0) {
+                    for (AnnotationInstanceInfo annotation : annotations) {
+                        if (SDK_WIDGET_ANNOTATION.equals(annotation.type().qualifiedName())) {
+                            widgets.add(clazz);
+                            annotated = true;
+                            break;
+                        } else if (SDK_LAYOUT_ANNOTATION.equals(annotation.type().qualifiedName())) {
+                            layouts.add(clazz);
+                            annotated = true;
+                            break;
+                        }
+                    }
+                }
+                
+                if (annotated == false) {
+                    // lets check if this is inside android.widget
+                    PackageInfo pckg = clazz.containingPackage();
+                    String packageName = pckg.name();
+                    if ("android.widget".equals(packageName) ||
+                            "android.view".equals(packageName)) {
+                        // now we check what this class inherits either from android.view.ViewGroup
+                        // or android.view.View, or android.view.ViewGroup.LayoutParams
+                        int type = checkInheritance(clazz);
+                        switch (type) {
+                            case TYPE_WIDGET:
+                                widgets.add(clazz);
+                                break;
+                            case TYPE_LAYOUT:
+                                layouts.add(clazz);
+                                break;
+                            case TYPE_LAYOUT_PARAM:
+                                layoutParams.add(clazz);
+                                break;
+                        }
+                    }
+                }
+            }
+        }
+
+        // now write the files, whether or not the list are empty.
+        // the SDK built requires those files to be present.
+
+        Collections.sort(activityActions);
+        writeValues(output + "/activity_actions.txt", activityActions);
+
+        Collections.sort(broadcastActions);
+        writeValues(output + "/broadcast_actions.txt", broadcastActions);
+
+        Collections.sort(serviceActions);
+        writeValues(output + "/service_actions.txt", serviceActions);
+
+        Collections.sort(categories);
+        writeValues(output + "/categories.txt", categories);
+        
+        // before writing the list of classes, we do some checks, to make sure the layout params
+        // are enclosed by a layout class (and not one that has been declared as a widget)
+        for (int i = 0 ; i < layoutParams.size();) {
+            ClassInfo layoutParamClass = layoutParams.get(i);
+            ClassInfo containingClass = layoutParamClass.containingClass();
+            if (containingClass == null || layouts.indexOf(containingClass) == -1) {
+                layoutParams.remove(i);
+            } else {
+                i++;
+            }
+        }
+        
+        writeClasses(output + "/widgets.txt", widgets, layouts, layoutParams);
+    }
+    
+    /**
+     * Writes a list of values into a text files.
+     * @param pathname the absolute os path of the output file.
+     * @param values the list of values to write.
+     */
+    private static void writeValues(String pathname, ArrayList<String> values) {
+        FileWriter fw = null;
+        BufferedWriter bw = null;
+        try {
+            fw = new FileWriter(pathname, false);
+            bw = new BufferedWriter(fw);
+            
+            for (String value : values) {
+                bw.append(value).append('\n');
+            }
+        } catch (IOException e) {
+            // pass for now
+        } finally {
+            try {
+                if (bw != null) bw.close();
+            } catch (IOException e) {
+                // pass for now
+            }
+            try {
+                if (fw != null) fw.close();
+            } catch (IOException e) {
+                // pass for now
+            }
+        }
+    }
+
+    /**
+     * Writes the widget/layout/layout param classes into a text files.
+     * @param pathname the absolute os path of the output file.
+     * @param widgets the list of widget classes to write.
+     * @param layouts the list of layout classes to write.
+     * @param layoutParams the list of layout param classes to write.
+     */
+    private static void writeClasses(String pathname, ArrayList<ClassInfo> widgets,
+            ArrayList<ClassInfo> layouts, ArrayList<ClassInfo> layoutParams) {
+        FileWriter fw = null;
+        BufferedWriter bw = null;
+        try {
+            fw = new FileWriter(pathname, false);
+            bw = new BufferedWriter(fw);
+            
+            // write the 3 types of classes.
+            for (ClassInfo clazz : widgets) {
+                writeClass(bw, clazz, 'W');
+            }
+            for (ClassInfo clazz : layoutParams) {
+                writeClass(bw, clazz, 'P');
+            }
+            for (ClassInfo clazz : layouts) {
+                writeClass(bw, clazz, 'L');
+            }
+        } catch (IOException e) {
+            // pass for now
+        } finally {
+            try {
+                if (bw != null) bw.close();
+            } catch (IOException e) {
+                // pass for now
+            }
+            try {
+                if (fw != null) fw.close();
+            } catch (IOException e) {
+                // pass for now
+            }
+        }
+    }
+
+    /**
+     * Writes a class name and its super class names into a {@link BufferedWriter}.
+     * @param writer the BufferedWriter to write into
+     * @param clazz the class to write
+     * @param prefix the prefix to put at the beginning of the line.
+     * @throws IOException
+     */
+    private static void writeClass(BufferedWriter writer, ClassInfo clazz, char prefix)
+            throws IOException {
+        writer.append(prefix).append(clazz.qualifiedName());
+        ClassInfo superClass = clazz;
+        while ((superClass = superClass.superclass()) != null) {
+            writer.append(' ').append(superClass.qualifiedName());
+        }
+        writer.append('\n');
+    }
+    
+    /**
+     * Checks the inheritance of {@link ClassInfo} objects. This method return
+     * <ul>
+     * <li>{@link #TYPE_LAYOUT}: if the class extends <code>android.view.ViewGroup</code></li>
+     * <li>{@link #TYPE_WIDGET}: if the class extends <code>android.view.View</code></li>
+     * <li>{@link #TYPE_LAYOUT_PARAM}: if the class extends <code>android.view.ViewGroup$LayoutParams</code></li>
+     * <li>{@link #TYPE_NONE}: in all other cases</li>
+     * </ul> 
+     * @param clazz the {@link ClassInfo} to check.
+     */
+    private static int checkInheritance(ClassInfo clazz) {
+        if ("android.view.ViewGroup".equals(clazz.qualifiedName())) {
+            return TYPE_LAYOUT;
+        } else if ("android.view.View".equals(clazz.qualifiedName())) {
+            return TYPE_WIDGET;
+        } else if ("android.view.ViewGroup.LayoutParams".equals(clazz.qualifiedName())) {
+            return TYPE_LAYOUT_PARAM;
+        }
+        
+        ClassInfo parent = clazz.superclass();
+        if (parent != null) {
+            return checkInheritance(parent);
+        }
+        
+        return TYPE_NONE;
+    }
+}
