Merge "Class: Get rid of most of java.lang.DexCache."
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index 46594c6..0e9a2bc 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -57,6 +57,7 @@
 #include "unicode/timezone.h"
 #include "unicode/ubrk.h"
 #include "unicode/ucal.h"
+#include "unicode/ucasemap.h"
 #include "unicode/uclean.h"
 #include "unicode/ucol.h"
 #include "unicode/ucurr.h"
diff --git a/luni/src/test/java/libcore/java/net/URLTest.java b/luni/src/test/java/libcore/java/net/URLTest.java
index 566c314..3a14063 100644
--- a/luni/src/test/java/libcore/java/net/URLTest.java
+++ b/luni/src/test/java/libcore/java/net/URLTest.java
@@ -194,14 +194,6 @@
         assertEquals(null, url.getRef());
     }
 
-    public void testAtSignInUserInfo() throws Exception {
-        try {
-            new URL("http://user@userhost.com:password@host");
-            fail();
-        } catch (MalformedURLException expected) {
-        }
-    }
-
     public void testUserNoPassword() throws Exception {
         URL url = new URL("http://user@host");
         assertEquals("user@host", url.getAuthority());
@@ -762,4 +754,12 @@
         assertEquals("/some/path", new URL("http://foobar.com/some/path#").getFile());
         assertEquals("/some/path", new URL("http://foobar.com/some/path?#").getFile());
     }
+
+    // http://b/33351987
+    public void testMultipleUserField() throws Exception {
+        final String host = "http://multiple@users@url.com";
+        URL url = new URL(host);
+        assertNull(url.getUserInfo());
+        assertTrue(url.getHost().isEmpty());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
index 564f7c9..dbbfeae 100644
--- a/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
+++ b/luni/src/test/java/libcore/java/nio/file/DefaultFileSystemProvider2Test.java
@@ -22,6 +22,7 @@
 import org.junit.runner.RunWith;
 
 import java.io.IOException;
+import java.net.URI;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
 import java.nio.channels.NonReadableChannelException;
@@ -47,6 +48,7 @@
 import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -69,6 +71,7 @@
 import static libcore.java.nio.file.FilesSetup.TEST_FILE_DATA_2;
 import static libcore.java.nio.file.FilesSetup.readFromFile;
 import static libcore.java.nio.file.FilesSetup.writeToFile;
+import static libcore.java.nio.file.LinuxFileSystemTestData.getPath_URI_InputOutputTestData;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
@@ -591,6 +594,55 @@
         } catch (NullPointerException expected) {}
     }
 
+    @Test
+    public void test_getPath() throws Exception {
+        List<LinuxFileSystemTestData.TestData> inputOutputTestCases = getPath_URI_InputOutputTestData();
+        for (LinuxFileSystemTestData.TestData inputOutputTestCase : inputOutputTestCases) {
+            assertEquals(inputOutputTestCase.output,
+                    provider.getPath(new URI(inputOutputTestCase.input)).toString());
+        }
+
+        // When URI is null.
+        try {
+            provider.getPath(null);
+            fail();
+        } catch (NullPointerException expected) {}
+
+        // When Schema is not supported.
+        try {
+            provider.getPath(new URI("scheme://d"));
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
+    @Test
+    public void test_getScheme() {
+        assertEquals("file", provider.getScheme());
+    }
+
+    @Test
+    public void test_installedProviders() {
+        assertNotNull(provider.installedProviders());
+    }
+
+    @Test
+    public void test_newFileSystem$URI$Map() throws Exception {
+        Path testPath = Paths.get("/");
+        assertNotNull(provider.getFileSystem(testPath.toUri()));
+
+        try {
+            provider.getFileSystem(null);
+            fail();
+        } catch (NullPointerException expected) {}
+
+        // Test the case when URI has illegal scheme.
+        URI stubURI = new URI("scheme://path");
+        try {
+            provider.getFileSystem(stubURI);
+            fail();
+        } catch (IllegalArgumentException expected) {}
+    }
+
     String readFromFileChannel(FileChannel fc) throws IOException {
         ByteBuffer bb = ByteBuffer.allocate(20);
         fc.read(bb);
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):