Add Cipher support to autodocs.

Ciphers are more complicated than other categories because providers can
declare that they provide a base algorithm but users request an
algorithm/mode/padding triple, so we need to investigate the possible
values of that triple and see which ones actually end up available.

We ignore all the PBE ciphers because they're a mess and we don't
want them to show up in the documentation.

The starting API level for AES/GCM/NOPADDING is actually an educated
guess, it's approximately correct but might be off by one or two.
I'll update it if I later get better information.

Bug: 35793879
Test: Ran run_update_crypto_support.sh
Change-Id: Ifb827818626690ff223f691c8297731790074283
diff --git a/tools/docs/crypto/data/crypto_support.json b/tools/docs/crypto/data/crypto_support.json
index d50eb2c..8e6cc4f 100644
--- a/tools/docs/crypto/data/crypto_support.json
+++ b/tools/docs/crypto/data/crypto_support.json
@@ -163,6 +163,411 @@
     {
       "algorithms": [
         {
+          "name": "AES/CBC/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CBC/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CBC/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CFB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CFB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CFB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CTR/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CTR/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CTR/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CTS/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CTS/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/CTS/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/ECB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/ECB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/ECB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/GCM/NOPADDING",
+          "supported_api_levels": "21+"
+        },
+        {
+          "name": "AES/OFB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/OFB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES/OFB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "AES_128/CBC/NOPADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_128/CBC/PKCS5PADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_128/ECB/NOPADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_128/ECB/PKCS5PADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_128/GCM/NOPADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_256/CBC/NOPADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_256/CBC/PKCS5PADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_256/ECB/NOPADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_256/ECB/PKCS5PADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "AES_256/GCM/NOPADDING",
+          "supported_api_levels": "26+"
+        },
+        {
+          "name": "ARC4/ECB/NOPADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CBC/ISO10126PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CBC/NOPADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CBC/PKCS5PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CFB/ISO10126PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CFB/NOPADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CFB/PKCS5PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CTR/ISO10126PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CTR/NOPADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CTR/PKCS5PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CTS/ISO10126PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CTS/NOPADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/CTS/PKCS5PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/ECB/ISO10126PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/ECB/NOPADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/ECB/PKCS5PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/OFB/ISO10126PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/OFB/NOPADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "BLOWFISH/OFB/PKCS5PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "DES/CBC/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CBC/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CBC/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CFB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CFB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CFB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CTR/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CTR/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CTR/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CTS/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CTS/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/CTS/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/ECB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/ECB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/ECB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/OFB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/OFB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DES/OFB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CBC/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CBC/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CBC/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CFB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CFB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CFB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CTR/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CTR/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CTR/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CTS/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CTS/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/CTS/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/ECB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/ECB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/ECB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/OFB/ISO10126PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/OFB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "DESEDE/OFB/PKCS5PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "RSA/ECB/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "RSA/ECB/OAEPPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "RSA/ECB/OAEPWITHSHA-224ANDMGF1PADDING",
+          "supported_api_levels": "23+"
+        },
+        {
+          "name": "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "RSA/ECB/OAEPWITHSHA-384ANDMGF1PADDING",
+          "supported_api_levels": "23+"
+        },
+        {
+          "name": "RSA/ECB/OAEPWITHSHA-512ANDMGF1PADDING",
+          "supported_api_levels": "23+"
+        },
+        {
+          "name": "RSA/ECB/PKCS1PADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "RSA/NONE/NOPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "RSA/NONE/OAEPPADDING",
+          "supported_api_levels": "1+"
+        },
+        {
+          "name": "RSA/NONE/OAEPWITHSHA-1ANDMGF1PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "RSA/NONE/OAEPWITHSHA-224ANDMGF1PADDING",
+          "supported_api_levels": "23+"
+        },
+        {
+          "name": "RSA/NONE/OAEPWITHSHA-256ANDMGF1PADDING",
+          "supported_api_levels": "10+"
+        },
+        {
+          "name": "RSA/NONE/OAEPWITHSHA-384ANDMGF1PADDING",
+          "supported_api_levels": "23+"
+        },
+        {
+          "name": "RSA/NONE/OAEPWITHSHA-512ANDMGF1PADDING",
+          "supported_api_levels": "23+"
+        },
+        {
+          "name": "RSA/NONE/PKCS1PADDING",
+          "supported_api_levels": "1+"
+        }
+      ],
+      "name": "Cipher"
+    },
+    {
+      "algorithms": [
+        {
           "name": "DH",
           "supported_api_levels": "1+"
         },
@@ -822,5 +1227,5 @@
       "name": "TrustManagerFactory"
     }
   ],
-  "last_updated": "2017-03-14 15:13:50 UTC"
+  "last_updated": "2017-03-16 10:29:21 UTC"
 }
\ No newline at end of file
diff --git a/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java b/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java
index 34aed4b..1cd8646 100644
--- a/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java
+++ b/tools/docs/crypto/src/java/libcore/java/security/ListProviders.java
@@ -16,6 +16,7 @@
 
 package libcore.java.security;
 
+import java.security.NoSuchAlgorithmException;
 import java.security.Provider;
 import java.security.Security;
 import java.util.ArrayList;
@@ -25,6 +26,8 @@
 import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
 
 /**
  * Prints a list of all algorithms provided by security providers.  Intended to be run
@@ -34,15 +37,50 @@
  */
 public class ListProviders {
 
+    private static final boolean SHOW_PROVIDER = false;
+
     // These algorithms were previously provided, but now are aliases for a different
     // algorithm.  For documentation purposes, we want to continue having them show up
     // as supported.
-    private static final Set<String> KNOWN_ALIASES = new HashSet<>(Arrays.asList(new String[]{
+    private static final Set<String> KNOWN_ALIASES = new TreeSet<>(Arrays.asList(new String[]{
             "Alg.Alias.Signature.DSA",
             "Alg.Alias.Signature.DSAwithSHA1",
             "Alg.Alias.Signature.ECDSA",
             "Alg.Alias.Signature.ECDSAwithSHA1",
     }));
+
+    // Ciphers come in algorithm/mode/padding combinations, and not all combinations are explicitly
+    // registered by the providers (sometimes only the base algorithm is registered).  While there
+    // is a mechanism for providers to specify which modes and/or paddings are supported for a
+    // given algorithm, none of our providers use it.  Thus, when a base algorithm is seen, all
+    // combinations of modes and paddings will be tried to see which ones are supported.
+    private static final Set<String> CIPHER_MODES = new TreeSet<>(Arrays.asList(new String[]{
+            "CBC",
+            "CFB",
+            "CTR",
+            "CTS",
+            "ECB",
+            "GCM",
+            "OFB",
+            "NONE",
+    }));
+    private static final Set<String> CIPHER_PADDINGS = new TreeSet<>(Arrays.asList(new String[]{
+            "NoPadding",
+            "OAEPPadding",
+            "OAEPwithSHA-1andMGF1Padding",
+            "OAEPwithSHA-224andMGF1Padding",
+            "OAEPwithSHA-256andMGF1Padding",
+            "OAEPwithSHA-384andMGF1Padding",
+            "OAEPwithSHA-512andMGF1Padding",
+            "PKCS1Padding",
+            "PKCS5Padding",
+            "ISO10126Padding",
+    }));
+
+    private static void print(Provider p, String type, String algorithm) {
+        System.out.println((SHOW_PROVIDER ? p.getName() + ": " : "") + type + " " + algorithm);
+    }
+
     public static void main(String[] argv) {
         System.out.println("BEGIN ALGORITHM LIST");
         for (Provider p : Security.getProviders()) {
@@ -58,12 +96,33 @@
                     });
             services.addAll(p.getServices());
             for (Provider.Service s : services) {
-                System.out.println(s.getType() + " " + s.getAlgorithm());
+                if (s.getType().equals("Cipher") && s.getAlgorithm().startsWith("PBE")) {
+                    // PBE ciphers are a mess and generally don't do anything but delegate
+                    // to the underlying cipher.  We don't want to document them.
+                    continue;
+                }
+                if (s.getType().equals("Cipher") && s.getAlgorithm().indexOf('/') == -1) {
+                    for (String mode : CIPHER_MODES) {
+                        for (String padding : CIPHER_PADDINGS) {
+                            try {
+                                String name = s.getAlgorithm() + "/" + mode + "/" + padding;
+                                Cipher.getInstance(name, p);
+                                print(p, s.getType(), name);
+                            } catch (NoSuchAlgorithmException
+                                    |NoSuchPaddingException
+                                    |IllegalArgumentException e) {
+                                // This combination doesn't work
+                            }
+                        }
+                    }
+                } else {
+                    print(p, s.getType(), s.getAlgorithm());
+                }
             }
             for (String alias : KNOWN_ALIASES) {
                 if (p.containsKey(alias)) {
                     String[] elements = alias.split("\\.");  // Split takes a regex
-                    System.out.println(elements[2] + " " + elements[3]);
+                    print(p, elements[2], elements[3]);
                 }
             }
         }
diff --git a/tools/docs/crypto/update_crypto_support.py b/tools/docs/crypto/update_crypto_support.py
index c8d19df..7d7861f 100755
--- a/tools/docs/crypto/update_crypto_support.py
+++ b/tools/docs/crypto/update_crypto_support.py
@@ -29,7 +29,6 @@
 import json
 import sys
 
-# TODO(b/35793879): Support more categories
 SUPPORTED_CATEGORIES = [
     'AlgorithmParameterGenerator',
     'AlgorithmParameters',
@@ -37,6 +36,7 @@
     'CertPathBuilder',
     'CertPathValidator',
     'CertStore',
+    'Cipher',
     'KeyAgreement',
     'KeyFactory',
     'KeyGenerator',
@@ -73,6 +73,12 @@
     # reverse.  X.509 is the official name of the standard, so use that.
     if name == "X509":
         name = "X.509"
+    # PKCS5PADDING and PKCS7PADDING are the same thing (more accurately, PKCS#5
+    # is a special case of PKCS#7), but providers are inconsistent in their
+    # naming.  Use PKCS5PADDING because that's what our docs have used
+    # historically.
+    if name.endswith("/PKCS7PADDING"):
+        name = name[:-1 * len("/PKCS7PADDING")] + "/PKCS5PADDING"
     return name
 
 def get_current_data(f):