diff --git a/tools/droiddoc/src/DroidDoc.java b/tools/droiddoc/src/DroidDoc.java
new file mode 100644
index 0000000..b0412c9
--- /dev/null
+++ b/tools/droiddoc/src/DroidDoc.java
@@ -0,0 +1,1326 @@
+/*
+ * 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();
+        }
+
+        // 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 = 1;
+            ClassInfo[] classesToCheck = pkg.ordinaryClasses();
+            while (pass < 5 ) {
+                switch(pass) {
+                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.out.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;
+                    System.out.println("Writing CS:  " + filename);
+                    ClearPage.write(data, templ, filename);
+                }
+                else if (len > 3 && ".jd".equals(templ.substring(len-3))) {
+                    String filename = templ.substring(0,len-3) + htmlExtension;
+                    System.out.println("Writing JD:  " + filename);
+                    DocFile.writePage(f.getAbsolutePath(), relative, filename);
+                }
+                else {
+//                    System.out.println("relative=" + relative
+//                            + " f.getAbsolutePath()=" + f.getAbsolutePath()
+//                            + " templ=" + templ);
+                    System.out.println("Copying:     " + templ);
+                    ClearPage.copyFile(f, templ);
+                }
+            }
+            else if (f.isDirectory()) {
+                System.out.println("Writing dir: " + relative + f.getName() + "/");
+                writeDirectory(f, relative + f.getName() + "/");
+            }
+        }
+    }
+
+    public static void writeHTMLPages()
+    {
+        File f = new File(ClearPage.htmlDir);
+        if (!f.isDirectory()) {
+            System.out.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.out.println("error writing file: " + filename);
+        }
+        finally {
+            if (stream != null) {
+                stream.close();
+            }
+        }
+    }
+
+    public static void writePackages(String filename)
+    {
+        System.out.println("Writing packages...");
+        HDF data = makePackageHDF();
+
+        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 = 1;
+            ClassInfo[] classesToCheck = pkg.ordinaryClasses();
+            while (pass < 5 ) {
+                switch(pass) {
+                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.out.println("Error reading package: " + pkg.name());
+                    break;
+                }
+                for (ClassInfo cl : classesToCheck) {
+                    if (!cl.isHidden()) {
+                        allHidden = false;
+                        break;
+                    }
+                }
+                if (!allHidden) {
+                    break;
+                }
+                pass++;
+            }
+            if (allHidden) {
+                continue;
+            }
+
+            writePackage(pkg);
+
+            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();
+        System.out.println("Writing " + 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 = filename.substring(0, filename.lastIndexOf('/')+1)
+            + "package-descr" + htmlExtension;
+        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() + ")";
+                        }
+                    }
+                } else {
+                    //System.out.println("not duplicate: " + sorted[i].label);
+                }
+                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 = makePackageHDF();
+
+        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);
+
+        System.out.println("Writing " + cl.name());
+        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;
+    }
+}
