Merge "Refactoring of the prototype data app"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 31836ad..8b12948 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -68,6 +68,18 @@
 #local_javac_flags+=-Xlint:all -Xlint:-serial,-deprecation,-unchecked
 local_javac_flags+=-Xmaxwarns 9999999
 
+# For user / userdebug builds, strip the local variable table and the local variable
+# type table. This has no bearing on stack traces, but will leave less information
+# available via JDWP.
+#
+# TODO: Should this be conditioned on a PRODUCT_ flag or should we just turn this
+# on for all builds. Also, name of the flag TBD.
+ifneq (,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO))
+ifneq (,$(filter userdebug user,$(TARGET_BUILD_VARIANT)))
+local_javac_flags+= -g:source,lines
+local_jack_flags+= -D jack.dex.debug.vars=false -D jack.dex.debug.vars.synthetic=false
+endif
+endif
 
 #
 # ICU4J related rules.
@@ -87,6 +99,7 @@
 LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs) $(android_icu4j_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JACK_FLAGS := $(local_jack_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -101,6 +114,7 @@
 LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JACK_FLAGS := $(local_jack_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -117,6 +131,7 @@
 LOCAL_JAVA_RESOURCE_DIRS := $(android_icu4j_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JACK_FLAGS := $(local_jack_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -138,6 +153,7 @@
 LOCAL_SRC_FILES := $(openjdk_lambda_stub_files) $(openjdk_lambda_duplicate_stub_files)
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JACK_FLAGS := $(local_jack_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -157,6 +173,7 @@
 LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JACK_FLAGS := $(local_jack_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
 LOCAL_DEX_PREOPT := false
@@ -191,6 +208,7 @@
 LOCAL_JAVA_RESOURCE_DIRS := $(android_icu4j_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JACK_FLAGS := $(local_jack_flags)
 LOCAL_DX_FLAGS := --core-library
 LOCAL_MODULE_TAGS := optional
 LOCAL_DEX_PREOPT := false
@@ -240,7 +258,8 @@
 	sqlite-jdbc \
 	tzdata-testing
 LOCAL_JAVACFLAGS := $(local_javac_flags)
-LOCAL_ERROR_PRONE_FLAGS := -Xep:TryFailThrowable:ERROR
+LOCAL_JACK_FLAGS := $(local_jack_flags)
+LOCAL_ERROR_PRONE_FLAGS := -Xep:TryFailThrowable:ERROR -Xep:ComparisonOutOfRange:ERROR
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 LOCAL_MODULE := core-tests
 include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -255,6 +274,7 @@
 LOCAL_JAVA_LIBRARIES := core-oj core-libart junit bouncycastle
 LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-bcpkix bouncycastle-ocsp
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JACK_FLAGS := $(local_jack_flags)
 LOCAL_MODULE := core-tests-support
 include $(BUILD_STATIC_JAVA_LIBRARY)
 endif
@@ -267,6 +287,7 @@
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVA_LIBRARIES := core-oj core-libart junit
 LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JACK_FLAGS := $(local_jack_flags)
 LOCAL_MODULE := jsr166-tests
 LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 include $(BUILD_STATIC_JAVA_LIBRARY)
@@ -280,6 +301,7 @@
     LOCAL_JAVA_LIBRARIES := core-oj core-libart okhttp bouncycastle
     LOCAL_STATIC_JAVA_LIBRARIES := testng
     LOCAL_JAVACFLAGS := $(local_javac_flags)
+    LOCAL_JACK_FLAGS := $(local_jack_flags)
     LOCAL_DX_FLAGS := --core-library
     LOCAL_MODULE_TAGS := optional
     LOCAL_JAVA_LANGUAGE_VERSION := 1.8
@@ -304,6 +326,7 @@
         okhttp \
         testng
     LOCAL_JAVACFLAGS := $(local_javac_flags)
+    LOCAL_JACK_FLAGS := $(local_jack_flags)
     LOCAL_DX_FLAGS := --core-library
     LOCAL_MODULE_TAGS := optional
     LOCAL_JAVA_LANGUAGE_VERSION := 1.8
diff --git a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
index 69110e0..a98e876 100644
--- a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelMulticastTest.java
@@ -236,7 +236,7 @@
         receiverChannel.join(group, networkInterface);
 
         String msg = "Hello World";
-        sendMulticastMessage(group, localAddress.getPort(), msg);
+        sendMulticastMessage(group, localAddress.getPort(), msg, networkInterface);
 
         // now verify that we received the data as expected
         ByteBuffer recvBuffer = ByteBuffer.allocate(100);
@@ -246,7 +246,7 @@
 
         // now verify that we didn't receive the second message
         String msg2 = "Hello World - Different Group";
-        sendMulticastMessage(group2, localAddress.getPort(), msg2);
+        sendMulticastMessage(group2, localAddress.getPort(), msg2, networkInterface);
         recvBuffer.position(0);
         SocketAddress sourceAddress2 = receiverChannel.receive(recvBuffer);
         assertNull(sourceAddress2);
@@ -1223,11 +1223,6 @@
                 && iface.getInetAddresses().hasMoreElements();
     }
 
-    private static void sendMulticastMessage(InetAddress group, int port, String msg)
-            throws IOException {
-        sendMulticastMessage(group, port, msg, null /* networkInterface */);
-    }
-
     private static void sendMulticastMessage(
             InetAddress group, int port, String msg, NetworkInterface sendingInterface)
             throws IOException {
diff --git a/luni/src/test/java/libcore/java/security/ProviderTest.java b/luni/src/test/java/libcore/java/security/ProviderTest.java
index 422fa6a..dab862a 100644
--- a/luni/src/test/java/libcore/java/security/ProviderTest.java
+++ b/luni/src/test/java/libcore/java/security/ProviderTest.java
@@ -286,8 +286,21 @@
         return p.getService(typeAndAlg[0], typeAndAlg[1]);
     }
 
+    /**
+     * Identifiers provided by Bouncy Castle that we exclude from consideration
+     * when checking that all Bouncy Castle identifiers are also covered by Conscrypt.
+     * Each block of excluded identifiers is preceded by the justification specific
+     * to those IDs.
+     */
     private static final Set<String> BC_OVERRIDE_EXCEPTIONS = new HashSet<>();
     static {
+        // A typo caused Bouncy Castle to accept these incorrect OIDs for AES, and they
+        // maintain these aliases for backwards compatibility.  We don't want to continue
+        // this in Conscrypt.
+        BC_OVERRIDE_EXCEPTIONS.add("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.2");
+        BC_OVERRIDE_EXCEPTIONS.add("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.22");
+        BC_OVERRIDE_EXCEPTIONS.add("Alg.Alias.AlgorithmParameters.2.16.840.1.101.3.4.42");
+
         // BC uses the same class to implement AlgorithmParameters.DES and
         // AlgorithmParameters.DESEDE.  Conscrypt doesn't support DES, so it doesn't
         // include an implementation of AlgorithmParameters.DES, and this isn't a problem.
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index 2b3347c..f995a7c 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -1495,9 +1495,11 @@
         final AlgorithmParameterSpec decryptSpec = getDecryptAlgorithmParameterSpec(encryptSpec, c);
         int decryptMode = getDecryptMode(algorithm);
 
-        test_Cipher_init_Decrypt_NullParameters(c, decryptMode, encryptKey, decryptSpec != null);
+        Key decryptKey = getDecryptKey(algorithm);
 
-        c.init(decryptMode, getDecryptKey(algorithm), decryptSpec);
+        test_Cipher_init_Decrypt_NullParameters(c, decryptMode, decryptKey, decryptSpec != null);
+
+        c.init(decryptMode, decryptKey, decryptSpec);
         assertEquals(cipherID + " getBlockSize() decryptMode",
                      getExpectedBlockSize(algorithm, decryptMode, providerName), c.getBlockSize());
         assertEquals(cipherID + " getOutputSize(0) decryptMode",
@@ -1547,7 +1549,7 @@
             byte[] cipherText = c.wrap(sk);
 
             // Unwrap it
-            c.init(Cipher.UNWRAP_MODE, getDecryptKey(algorithm), decryptSpec);
+            c.init(Cipher.UNWRAP_MODE, decryptKey, decryptSpec);
             Key decryptedKey = c.unwrap(cipherText, sk.getAlgorithm(), Cipher.SECRET_KEY);
 
             assertEquals(cipherID
@@ -1568,7 +1570,7 @@
                 byte[] cipherText2 = c.doFinal(getActualPlainText(algorithm));
                 assertEquals(cipherID, Arrays.toString(cipherText), Arrays.toString(cipherText2));
             }
-            c.init(Cipher.DECRYPT_MODE, getDecryptKey(algorithm), decryptSpec);
+            c.init(Cipher.DECRYPT_MODE, decryptKey, decryptSpec);
             if (isAEAD(algorithm)) {
                 c.updateAAD(new byte[24]);
             }
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestAES.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestAES.java
index a53b57d..ae87ca5 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestAES.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestAES.java
@@ -15,6 +15,12 @@
  */
 package libcore.javax.crypto.spec;
 
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Base64;
 import javax.crypto.spec.IvParameterSpec;
 import tests.security.AlgorithmParameterSymmetricHelper;
 import tests.security.AlgorithmParametersTest;
@@ -27,8 +33,35 @@
         (byte) 0x04, (byte) 0x08, (byte) 0x68, (byte) 0xC8,
         (byte) 0xFF, (byte) 0x64, (byte) 0x72, (byte) 0xF5 };
 
+    // See README.ASN1 for how to understand and reproduce this data
+
+    // asn1=FORMAT:HEX,OCTETSTRING:040868C8FF6472F5040868C8
+    private static final String ENCODED_DATA = "BBAECGjI/2Ry9QQIaMj/ZHL1";
+
     public AlgorithmParametersTestAES() {
         super("AES", new AlgorithmParameterSymmetricHelper("AES", "CBC/PKCS5PADDING", 128), new IvParameterSpec(parameterData));
     }
 
+    public void testEncoding() throws Exception {
+        for (Provider p : Security.getProviders()) {
+            AlgorithmParameters params;
+            try {
+                params = AlgorithmParameters.getInstance("AES", p);
+            } catch (NoSuchAlgorithmException e) {
+                // This provider doesn't support AES, ignore
+                continue;
+            }
+
+            params.init(new IvParameterSpec(parameterData));
+            assertEquals("Provider: " + p.getName(),
+                    ENCODED_DATA, Base64.getEncoder().encodeToString(params.getEncoded()));
+
+            params = AlgorithmParameters.getInstance("AES", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA));
+            assertTrue("Provider: " + p.getName(),
+                    Arrays.equals(parameterData,
+                            params.getParameterSpec(IvParameterSpec.class).getIV()));
+        }
+    }
+
 }
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDES.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDES.java
index 8c79d4c..e59ba3f 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDES.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDES.java
@@ -15,6 +15,12 @@
  */
 package libcore.javax.crypto.spec;
 
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Base64;
 import javax.crypto.spec.IvParameterSpec;
 import tests.security.AlgorithmParameterSymmetricHelper;
 import tests.security.AlgorithmParametersTest;
@@ -25,8 +31,35 @@
         (byte) 0x04, (byte) 0x08, (byte) 0x68, (byte) 0xC8,
         (byte) 0xFF, (byte) 0x64, (byte) 0x72, (byte) 0xF5 };
 
+    // See README.ASN1 for how to understand and reproduce this data
+
+    // asn1=FORMAT:HEX,OCTETSTRING:040868C8FF6472F5
+    private static final String ENCODED_DATA = "BAgECGjI/2Ry9Q==";
+
     public AlgorithmParametersTestDES() {
         super("DES", new AlgorithmParameterSymmetricHelper("DES", "CBC/PKCS5PADDING", 56), new IvParameterSpec(parameterData));
     }
 
+    public void testEncoding() throws Exception {
+        for (Provider p : Security.getProviders()) {
+            AlgorithmParameters params;
+            try {
+                params = AlgorithmParameters.getInstance("DES", p);
+            } catch (NoSuchAlgorithmException e) {
+                // This provider doesn't support DES, ignore
+                continue;
+            }
+
+            params.init(new IvParameterSpec(parameterData));
+            assertEquals("Provider: " + p.getName(),
+                    ENCODED_DATA, Base64.getEncoder().encodeToString(params.getEncoded()));
+
+            params = AlgorithmParameters.getInstance("DES", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA));
+            assertTrue("Provider: " + p.getName(),
+                    Arrays.equals(parameterData,
+                            params.getParameterSpec(IvParameterSpec.class).getIV()));
+        }
+    }
+
 }
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDESede.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDESede.java
index 24d044e..9cb7c5d 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDESede.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDESede.java
@@ -15,6 +15,12 @@
  */
 package libcore.javax.crypto.spec;
 
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Base64;
 import javax.crypto.spec.IvParameterSpec;
 import tests.security.AlgorithmParameterSymmetricHelper;
 import tests.security.AlgorithmParametersTest;
@@ -25,8 +31,35 @@
         (byte) 0x04, (byte) 0x08, (byte) 0x68, (byte) 0xC8,
         (byte) 0xFF, (byte) 0x64, (byte) 0x72, (byte) 0xF5 };
 
+    // See README.ASN1 for how to understand and reproduce this data
+
+    // asn1=FORMAT:HEX,OCTETSTRING:040868C8FF6472F5
+    private static final String ENCODED_DATA = "BAgECGjI/2Ry9Q==";
+
     public AlgorithmParametersTestDESede() {
         super("DESede", new AlgorithmParameterSymmetricHelper("DESede", "CBC/PKCS5PADDING", 112), new IvParameterSpec(parameterData));
     }
 
+    public void testEncoding() throws Exception {
+        for (Provider p : Security.getProviders()) {
+            AlgorithmParameters params;
+            try {
+                params = AlgorithmParameters.getInstance("DESede", p);
+            } catch (NoSuchAlgorithmException e) {
+                // This provider doesn't support DESede, ignore
+                continue;
+            }
+
+            params.init(new IvParameterSpec(parameterData));
+            assertEquals("Provider: " + p.getName(),
+                    ENCODED_DATA, Base64.getEncoder().encodeToString(params.getEncoded()));
+
+            params = AlgorithmParameters.getInstance("DESede", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA));
+            assertTrue("Provider: " + p.getName(),
+                    Arrays.equals(parameterData,
+                            params.getParameterSpec(IvParameterSpec.class).getIV()));
+        }
+    }
+
 }
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDSA.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDSA.java
index 4918fdc..b524161 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDSA.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestDSA.java
@@ -16,7 +16,13 @@
 package libcore.javax.crypto.spec;
 
 import java.math.BigInteger;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
 import java.security.spec.DSAParameterSpec;
+import java.util.Base64;
+
 import tests.security.AlgorithmParameterSignatureHelper;
 import tests.security.AlgorithmParametersTest;
 
@@ -89,6 +95,20 @@
             (byte) 0x82, (byte) 0xC9, (byte) 0x75,
     };
 
+    // The ASN.1 module for DSA is defined in RFC 3279 section 3. See README.ASN1 for how
+    // to understand and reproduce this data.
+
+    // asn1=SEQUENCE:dsa
+    // [dsa]
+    // p=INT:0xE6415877765A4A53F1D6C87D671F2FFADEB7AACDD75DD0E9B1DAFE42BECC42522E01D216B15BC442F9550FE2D501D27E22F6C1FE5C6ACF821B5C46668BAFDF44E20EA358F7A324E384A616E0CA725507A0997BF8B15A84365AC86AFEA6B41B3A0A006B72DC0CD1092511686B75DE2C1AC23ACBA017CA2DEEA25A9D1F331B076D
+    // q=INT:0x9B39D0020FE99616C525F794A92CD0255B6EE08F
+    // g=INT:0x5E9C955F7E91474D68A41C443BEC0A7E5954F7EF42FB6395082F4AD3BC799DBAD88A8384AE5B2680B3FB9CA3CFF40AD5B665651A4FC0863BE6FB4E9E490A8C772D930BCA810709C471FDC8C7D1A3D0BB7D92748B3B2A451F5D8590E3FB0E16BA8ADE100FE00F37A7C1DCBC00B8240FF65FB1A89ADB9F365445BDC0E82782C975
+    private static final String ENCODED_DATA = "MIIBHgKBgQDmQVh3dlpKU/HWyH1nHy/63reqzddd0Omx2v5"
+            + "CvsxCUi4B0haxW8RC+VUP4tUB0n4i9sH+XGrPghtcRmaLr99E4g6jWPejJOOEphbgynJVB6CZe/ixWoQ"
+            + "2Wshq/qa0GzoKAGty3AzRCSURaGt13iwawjrLoBfKLe6iWp0fMxsHbQIVAJs50AIP6ZYWxSX3lKks0CV"
+            + "bbuCPAoGAXpyVX36RR01opBxEO+wKfllU9+9C+2OVCC9K07x5nbrYioOErlsmgLP7nKPP9ArVtmVlGk/"
+            + "Ahjvm+06eSQqMdy2TC8qBBwnEcf3Ix9Gj0Lt9knSLOypFH12FkOP7Dha6it4QD+APN6fB3LwAuCQP9l+"
+            + "xqJrbnzZURb3A6CeCyXU=";
 
     public AlgorithmParametersTestDSA() {
         super("DSA", new AlgorithmParameterSignatureHelper<DSAParameterSpec>(
@@ -96,4 +116,31 @@
                 new BigInteger(1, P), new BigInteger(1, Q), new BigInteger(1, G)));
     }
 
+    public void testEncoding() throws Exception {
+        for (Provider p : Security.getProviders()) {
+            AlgorithmParameters params;
+            try {
+                params = AlgorithmParameters.getInstance("DSA", p);
+            } catch (NoSuchAlgorithmException e) {
+                // This provider doesn't support DSA, ignore
+                continue;
+            }
+
+            DSAParameterSpec spec = new DSAParameterSpec(
+                    new BigInteger(1, P), new BigInteger(1, Q), new BigInteger(1, G));
+
+            params.init(spec);
+            assertEquals("Provider: " + p.getName(),
+                    ENCODED_DATA, Base64.getEncoder().encodeToString(params.getEncoded()));
+
+            params = AlgorithmParameters.getInstance("DSA", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA));
+            DSAParameterSpec derivedSpec = params.getParameterSpec(DSAParameterSpec.class);
+
+            assertEquals("Provider: " + p.getName(), new BigInteger(1, P), derivedSpec.getP());
+            assertEquals("Provider: " + p.getName(), new BigInteger(1, Q), derivedSpec.getQ());
+            assertEquals("Provider: " + p.getName(), new BigInteger(1, G), derivedSpec.getG());
+        }
+    }
+
 }
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestGCM.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestGCM.java
new file mode 100644
index 0000000..cb99c9a
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestGCM.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+package libcore.javax.crypto.spec;
+
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Base64;
+import javax.crypto.spec.GCMParameterSpec;
+
+import tests.security.AlgorithmParameterSymmetricHelper;
+import tests.security.AlgorithmParametersTest;
+
+public class AlgorithmParametersTestGCM extends AlgorithmParametersTest {
+
+    private static final byte[] IV = new byte[] {
+        (byte) 0x04, (byte) 0x08, (byte) 0x68, (byte) 0xC8,
+        (byte) 0xFF, (byte) 0x64, (byte) 0x72, (byte) 0xF5,
+        (byte) 0x04, (byte) 0x08, (byte) 0x68, (byte) 0xC8 };
+
+    private static final int TLEN = 96;
+
+    // The ASN.1 encoding for GCM params (specified in RFC 5084 section 3.2) specifies
+    // a default value of 12 for TLEN, so both values with and without TLEN should work.
+    // See README.ASN1 for how to understand and reproduce this data.
+
+    // asn1=SEQUENCE:gcm
+    // [gcm]
+    // iv=FORMAT:HEX,OCTETSTRING:040868C8FF6472F5040868C8
+    private static final String ENCODED_DATA_NO_TLEN = "MA4EDAQIaMj/ZHL1BAhoyA==";
+
+    // asn1=SEQUENCE:gcm
+    // [gcm]
+    // iv=FORMAT:HEX,OCTETSTRING:040868C8FF6472F5040868C8
+    // tlen=INT:12
+    private static final String ENCODED_DATA_TLEN = "MBEEDAQIaMj/ZHL1BAhoyAIBDA==";
+
+    public AlgorithmParametersTestGCM() {
+        super("GCM", new AlgorithmParameterSymmetricHelper("AES", "GCM/NOPADDING", 128), new GCMParameterSpec(TLEN, IV));
+    }
+
+    public void testEncoding() throws Exception {
+        for (Provider p : Security.getProviders()) {
+            AlgorithmParameters params;
+            try {
+                params = AlgorithmParameters.getInstance("GCM", p);
+            } catch (NoSuchAlgorithmException e) {
+                // This provider doesn't support AES/GCM, ignore
+                continue;
+            }
+
+            params.init(new GCMParameterSpec(TLEN, IV));
+            String encoded = Base64.getEncoder().encodeToString(params.getEncoded());
+            assertTrue("Provider: " + p.getName() + ", encoded: " + encoded,
+                    encoded.equals(ENCODED_DATA_TLEN) || encoded.equals(ENCODED_DATA_NO_TLEN));
+
+            params = AlgorithmParameters.getInstance("GCM", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA_NO_TLEN));
+            GCMParameterSpec spec = params.getParameterSpec(GCMParameterSpec.class);
+            assertEquals("Provider: " + p.getName(), TLEN, spec.getTLen());
+            assertTrue("Provider: " + p.getName(), Arrays.equals(IV, spec.getIV()));
+
+            params = AlgorithmParameters.getInstance("GCM", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA_TLEN));
+            spec = params.getParameterSpec(GCMParameterSpec.class);
+            assertEquals("Provider: " + p.getName(), TLEN, spec.getTLen());
+            assertTrue("Provider: " + p.getName(), Arrays.equals(IV, spec.getIV()));
+        }
+    }
+
+}
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestOAEP.java b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestOAEP.java
index 0a75d2c..7123e42 100644
--- a/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestOAEP.java
+++ b/luni/src/test/java/libcore/javax/crypto/spec/AlgorithmParametersTestOAEP.java
@@ -15,7 +15,13 @@
  */
 package libcore.javax.crypto.spec;
 
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+import java.security.Security;
 import java.security.spec.MGF1ParameterSpec;
+import java.util.Arrays;
+import java.util.Base64;
 import javax.crypto.spec.OAEPParameterSpec;
 import javax.crypto.spec.PSource;
 import tests.security.AlgorithmParameterAsymmetricHelper;
@@ -23,8 +29,161 @@
 
 public class AlgorithmParametersTestOAEP extends AlgorithmParametersTest {
 
+    // The ASN.1 encoding for OAEP params (specified in RFC 4055 section 4.1) specifies
+    // default values for all parameters, so we need to consider encodings with those
+    // values both explicitly specified and unspecified.  When encoding values, it is required
+    // that default values are left empty, but implementations must be able to parse explicitly-
+    // specified defaults as well.
+    //
+    // See README.ASN1 for how to understand and reproduce this data.
+
+    // asn1=SEQUENCE
+    private static final String ENCODED_DATA_ALL_DEFAULTS = "MAA=";
+
+    // asn1=SEQUENCE:oaep
+    // [oaep]
+    // hashFunc=EXP:0,SEQUENCE:sha1
+    // maskGenFunc=EXP:1,SEQUENCE:mgf1
+    // pSourceFunc=EXP:2,SEQUENCE:pSpecified
+    // [mgf1]
+    // oid=OID:1.2.840.113549.1.1.8
+    // params=SEQUENCE:sha1
+    // [pSpecified]
+    // oid=OID:1.2.840.113549.1.1.9
+    // val=OCTETSTRING:
+    // [sha1]
+    // oid=OID:sha1
+    // params=NULL
+    private static final String ENCODED_DATA_EXPLICIT_DEFAULTS =
+            "MDigCzAJBgUrDgMCGgUAoRgwFgYJKoZIhvcNAQEIMAkGBSsOAwIaBQCiDzANBgkqhkiG9w0BAQkEAA==";
+
+    // Base64 version of ASN.1-encoded data with none of the default values.  Specifically:
+    // SHA-256 hashFunc, MGF1-SHA-384 maskGenFunc, and [1, 2, 3, 4] pSourceFunc
+
+    // asn1=SEQUENCE:oaep
+    // [oaep]
+    // hashFunc=EXP:0,SEQUENCE:sha256
+    // maskGenFunc=EXP:1,SEQUENCE:mgf1
+    // pSourceFunc=EXP:2,SEQUENCE:pSpecified
+    // [sha256]
+    // oid=OID:sha256
+    // params=NULL
+    // [mgf1]
+    // oid=OID:1.2.840.113549.1.1.8
+    // params=SEQUENCE:sha384
+    // [sha384]
+    // oid=OID:sha384
+    // params=NULL
+    // [pSpecified]
+    // oid=OID:1.2.840.113549.1.1.9
+    // val=FORMAT:HEX,OCTETSTRING:01020304
+    private static final String ENCODED_DATA_NON_DEFAULTS = "MESgDzANBglghkgBZQMEAgEFAKEc"
+            + "MBoGCSqGSIb3DQEBCDANBglghkgBZQMEAgIFAKITMBEGCSqGSIb3DQEBCQQEAQIDBA==";
+
+    // Base64 version of ASN.1-encoded data with some default and some non-default values.
+    // Specifically, SHA-1 hashFunc (default), MGF1-SHA-512 maskGenFunc (non-default),
+    // empty pSourceFunc (default)
+
+    // asn1=SEQUENCE:oaep
+    // [oaep]
+    // maskGenFunc=EXP:1,SEQUENCE:mgf1
+    // [mgf1]
+    // oid=OID:1.2.840.113549.1.1.8
+    // params=SEQUENCE:sha512
+    // [sha512]
+    // oid=OID:sha512
+    // params=NULL
+    private static final String ENCODED_DATA_MIXED = "MB6hHDAaBgkqhkiG9w0BAQgwDQYJYIZIAWUDBAIDBQA=";
+
     public AlgorithmParametersTestOAEP() {
         super("OAEP", new AlgorithmParameterAsymmetricHelper("RSA"), new OAEPParameterSpec("SHA-1", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT));
     }
 
+    public void testEncoding() throws Exception {
+        for (Provider p : Security.getProviders()) {
+            AlgorithmParameters params;
+            try {
+                params = AlgorithmParameters.getInstance("OAEP", p);
+            } catch (NoSuchAlgorithmException e) {
+                // This provider doesn't support OAEP, ignore
+                continue;
+            }
+
+            OAEPParameterSpec spec = new OAEPParameterSpec(
+                    "SHA-1", "MGF1", MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
+            params.init(spec);
+            assertEquals("Provider: " + p.getName(),
+                    ENCODED_DATA_ALL_DEFAULTS,
+                    Base64.getEncoder().encodeToString(params.getEncoded()));
+
+            params = AlgorithmParameters.getInstance("OAEP", p);
+            spec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA384,
+                    new PSource.PSpecified(new byte[] {1, 2, 3, 4}));
+            params.init(spec);
+            assertEquals("Provider: " + p.getName(),
+                    ENCODED_DATA_NON_DEFAULTS,
+                    Base64.getEncoder().encodeToString(params.getEncoded()));
+
+            params = AlgorithmParameters.getInstance("OAEP", p);
+            spec = new OAEPParameterSpec(
+                    "SHA-1", "MGF1", MGF1ParameterSpec.SHA512, PSource.PSpecified.DEFAULT);
+            params.init(spec);
+            assertEquals("Provider: " + p.getName(),
+                    ENCODED_DATA_MIXED,
+                    Base64.getEncoder().encodeToString(params.getEncoded()));
+
+            params = AlgorithmParameters.getInstance("OAEP", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA_ALL_DEFAULTS));
+            OAEPParameterSpec producedSpec = params.getParameterSpec(OAEPParameterSpec.class);
+
+            assertEquals("Provider: " + p.getName(), "SHA-1", producedSpec.getDigestAlgorithm());
+            assertEquals("Provider: " + p.getName(), "MGF1", producedSpec.getMGFAlgorithm());
+            assertEquals("Provider: " + p.getName(),
+                    MGF1ParameterSpec.SHA1.getDigestAlgorithm(),
+                    ((MGF1ParameterSpec) producedSpec.getMGFParameters()).getDigestAlgorithm());
+            assertTrue("Provider: " + p.getName(),
+                    Arrays.equals(PSource.PSpecified.DEFAULT.getValue(),
+                            ((PSource.PSpecified) producedSpec.getPSource()).getValue()));
+
+            params = AlgorithmParameters.getInstance("OAEP", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA_EXPLICIT_DEFAULTS));
+            producedSpec = params.getParameterSpec(OAEPParameterSpec.class);
+
+            assertEquals("Provider: " + p.getName(), "SHA-1", producedSpec.getDigestAlgorithm());
+            assertEquals("Provider: " + p.getName(), "MGF1", producedSpec.getMGFAlgorithm());
+            assertEquals("Provider: " + p.getName(),
+                    MGF1ParameterSpec.SHA1.getDigestAlgorithm(),
+                    ((MGF1ParameterSpec) producedSpec.getMGFParameters()).getDigestAlgorithm());
+            assertTrue("Provider: " + p.getName(),
+                    Arrays.equals(PSource.PSpecified.DEFAULT.getValue(),
+                            ((PSource.PSpecified) producedSpec.getPSource()).getValue()));
+
+            params = AlgorithmParameters.getInstance("OAEP", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA_NON_DEFAULTS));
+            producedSpec = params.getParameterSpec(OAEPParameterSpec.class);
+
+            assertEquals("Provider: " + p.getName(), "SHA-256", producedSpec.getDigestAlgorithm());
+            assertEquals("Provider: " + p.getName(), "MGF1", producedSpec.getMGFAlgorithm());
+            assertEquals("Provider: " + p.getName(),
+                    MGF1ParameterSpec.SHA384.getDigestAlgorithm(),
+                    ((MGF1ParameterSpec) producedSpec.getMGFParameters()).getDigestAlgorithm());
+            assertTrue("Provider: " + p.getName(),
+                    Arrays.equals(new byte[] {1, 2, 3, 4},
+                            ((PSource.PSpecified) producedSpec.getPSource()).getValue()));
+
+            params = AlgorithmParameters.getInstance("OAEP", p);
+            params.init(Base64.getDecoder().decode(ENCODED_DATA_MIXED));
+            producedSpec = params.getParameterSpec(OAEPParameterSpec.class);
+
+            assertEquals("Provider: " + p.getName(), "SHA-1", producedSpec.getDigestAlgorithm());
+            assertEquals("Provider: " + p.getName(), "MGF1", producedSpec.getMGFAlgorithm());
+            assertEquals("Provider: " + p.getName(),
+                    MGF1ParameterSpec.SHA512.getDigestAlgorithm(),
+                    ((MGF1ParameterSpec) producedSpec.getMGFParameters()).getDigestAlgorithm());
+            assertTrue("Provider: " + p.getName(),
+                    Arrays.equals(PSource.PSpecified.DEFAULT.getValue(),
+                            ((PSource.PSpecified) producedSpec.getPSource()).getValue()));
+        }
+    }
+
 }
diff --git a/luni/src/test/java/libcore/javax/crypto/spec/README.ASN1 b/luni/src/test/java/libcore/javax/crypto/spec/README.ASN1
new file mode 100644
index 0000000..67ffae3
--- /dev/null
+++ b/luni/src/test/java/libcore/javax/crypto/spec/README.ASN1
@@ -0,0 +1,14 @@
+Many tests in this package check the ASN.1 encoding for various kinds of parameters.  The openssl
+command line tool can be used to view and encode data in ASN.1.
+
+Test data for encoding tests is preceded by its definition in the OpenSSL generation string
+format described at https://wiki.openssl.org/index.php/Manual:ASN1_generate_nconf(3).  To
+reproduce the base64-encoded values in the test files, do:
+
+# Put data definition in a file, eg input.cnf
+openssl asn1parse -genconf input.cnf -out /tmp/asn1.der
+openssl base64 -in /tmp/asn1.der
+
+To view the ASN.1 data encoded in a base64-encoded string, do:
+
+echo 'BASE64-ENCODED DATA HERE' | openssl asn1parse -i
diff --git a/luni/src/test/java/tests/security/cert/CertificateTest.java b/luni/src/test/java/tests/security/cert/CertificateTest.java
index 156ccd2..d49b08f 100644
--- a/luni/src/test/java/tests/security/cert/CertificateTest.java
+++ b/luni/src/test/java/tests/security/cert/CertificateTest.java
@@ -174,7 +174,7 @@
         byte[] actualEncoding = actual.getEncoded();
         assertTrue(Arrays.equals(expectedEncoding, actualEncoding));
 
-        assertFalse(expectedEncoding[4] == 200);
+        assertFalse(expectedEncoding[4] == (byte) 200);
         expectedEncoding[4] = (byte) 200;
         try {
             cf.generateCertificate(new ByteArrayInputStream(expectedEncoding));
diff --git a/tzdata/prototype_updater/src/libcore/tzdata/prototype_updater/RulesCheckReceiver.java b/tzdata/prototype_updater/src/libcore/tzdata/prototype_updater/RulesCheckReceiver.java
index 9f3a3b8..44980a5 100644
--- a/tzdata/prototype_updater/src/libcore/tzdata/prototype_updater/RulesCheckReceiver.java
+++ b/tzdata/prototype_updater/src/libcore/tzdata/prototype_updater/RulesCheckReceiver.java
@@ -152,8 +152,8 @@
 
         // Decide whether to proceed with the install.
         RulesState rulesState = mRulesManager.getRulesState();
-        if (!(rulesState.isDistroFormatVersionSupported(distroVersionInfo.mDistroFormatVersion)
-            && rulesState.isSystemVersionOlderThan(distroVersionInfo.mDistroRulesVersion))) {
+        if (!rulesState.isDistroFormatVersionSupported(distroVersionInfo.mDistroFormatVersion)
+            || rulesState.isSystemVersionNewerThan(distroVersionInfo.mDistroRulesVersion)) {
             // Nothing to do.
             handleCheckComplete(checkToken, true /* success */);
             return;