Merge "Use JCA names for block modes, paddings, and digests."
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9269f60..b063209 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -261,6 +261,8 @@
         IActivityManager.ContentProviderHolder holder;
         boolean acquiring = true;
         int requests = 1;
+        // Set if there was a runtime exception when trying to acquire the provider.
+        RuntimeException runtimeException = null;
     }
 
     // The lock of mProviderMap protects the following variables.
@@ -4670,39 +4672,55 @@
         }
 
         IActivityManager.ContentProviderHolder holder = null;
-        if (first) {
-            // Multiple threads may try to acquire the same provider at the same time.
-            // When this happens, we only let the first one really gets provider.
-            // Other threads just wait for its result.
-            // Note that we cannot hold the lock while acquiring and installing the
-            // provider since it might take a long time to run and it could also potentially
-            // be re-entrant in the case where the provider is in the same process.
-            try {
+        try {
+            if (first) {
+                // Multiple threads may try to acquire the same provider at the same time.
+                // When this happens, we only let the first one really gets provider.
+                // Other threads just wait for its result.
+                // Note that we cannot hold the lock while acquiring and installing the
+                // provider since it might take a long time to run and it could also potentially
+                // be re-entrant in the case where the provider is in the same process.
                 holder = ActivityManagerNative.getDefault().getContentProvider(
                         getApplicationThread(), auth, userId, stable);
-            } catch (RemoteException ex) {
-            }
-            synchronized (r) {
-                r.holder = holder;
-                r.acquiring = false;
-                r.notifyAll();
-            }
-        } else {
-            synchronized (r) {
-                while (r.acquiring) {
-                    try {
-                        r.wait();
-                    } catch (InterruptedException e) {
+            } else {
+                synchronized (r) {
+                    while (r.acquiring) {
+                        try {
+                            r.wait();
+                        } catch (InterruptedException e) {
+                        }
                     }
+                    holder = r.holder;
                 }
-                holder = r.holder;
+            }
+        } catch (RemoteException ex) {
+        } catch (RuntimeException e) {
+            synchronized (r) {
+                r.runtimeException = e;
+            }
+        } finally {
+            if (first) {
+                synchronized (r) {
+                    r.holder = holder;
+                    r.acquiring = false;
+                    r.notifyAll();
+                }
+            }
+
+            synchronized (mAcquiringProviderMap) {
+                if (--r.requests == 0) {
+                    mAcquiringProviderMap.remove(key);
+                }
+            }
+
+            if (r.runtimeException != null) {
+                // Was set when the first thread tried to acquire the provider,
+                // but we should make sure it is thrown for all threads trying to
+                // acquire the provider.
+                throw r.runtimeException;
             }
         }
-        synchronized (mAcquiringProviderMap) {
-            if (--r.requests == 0) {
-                mAcquiringProviderMap.remove(key);
-            }
-        }
+
         if (holder == null) {
             Slog.e(TAG, "Failed to find provider info for " + auth);
             return null;
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index bb9c465..d3953b3 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -47,12 +47,11 @@
     public static final int KM_TAG_PURPOSE = KM_ENUM_REP | 1;
     public static final int KM_TAG_ALGORITHM = KM_ENUM | 2;
     public static final int KM_TAG_KEY_SIZE = KM_INT | 3;
-    public static final int KM_TAG_BLOCK_MODE = KM_ENUM | 4;
-    public static final int KM_TAG_DIGEST = KM_ENUM | 5;
-    public static final int KM_TAG_MAC_LENGTH = KM_INT | 6;
-    public static final int KM_TAG_PADDING = KM_ENUM | 7;
-    public static final int KM_TAG_RETURN_UNAUTHED = KM_BOOL | 8;
-    public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 9;
+    public static final int KM_TAG_BLOCK_MODE = KM_ENUM_REP | 4;
+    public static final int KM_TAG_DIGEST = KM_ENUM_REP | 5;
+    public static final int KM_TAG_PADDING = KM_ENUM_REP | 6;
+    public static final int KM_TAG_RETURN_UNAUTHED = KM_BOOL | 7;
+    public static final int KM_TAG_CALLER_NONCE = KM_BOOL | 8;
 
     public static final int KM_TAG_RESCOPING_ADD = KM_ENUM_REP | 101;
     public static final int KM_TAG_RESCOPING_DEL = KM_ENUM_REP | 102;
@@ -85,6 +84,7 @@
     public static final int KM_TAG_NONCE = KM_BYTES | 1001;
     public static final int KM_TAG_CHUNK_LENGTH = KM_INT | 1002;
     public static final int KM_TAG_AUTH_TOKEN = KM_BYTES | 1003;
+    public static final int KM_TAG_MAC_LENGTH = KM_INT | 1004;
 
     // Algorithm values.
     public static final int KM_ALGORITHM_RSA = 1;
diff --git a/keystore/java/android/security/EcIesParameterSpec.java b/keystore/java/android/security/EcIesParameterSpec.java
new file mode 100644
index 0000000..0f19812
--- /dev/null
+++ b/keystore/java/android/security/EcIesParameterSpec.java
@@ -0,0 +1,287 @@
+package android.security;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+
+/**
+ * {@link AlgorithmParameterSpec} for ECIES (Integrated Encryption Scheme using Elliptic Curve
+ * cryptography) based on {@code ISO/IEC 18033-2}.
+ *
+ * <p>ECIES is a hybrid authenticated encryption scheme. Encryption is performed using an Elliptic
+ * Curve (EC) public key. The resulting ciphertext can be decrypted only using the corresponding EC
+ * private key. The scheme is called hybrid because the EC key is only used to securely encapsulate
+ * symmetric key material. Encryption of plaintext and authentication of the corresponding
+ * ciphertext is performed using symmetric cryptography.
+ *
+ * <p>Encryption using ECIES consists of two stages:
+ * <ol>
+ * <li>Key Encapsulation Mechanism (KEM) randomly generates symmetric key material and securely
+ * encapsulates it in the output so that it can be extracted by the KEM when decrypting.
+ * Encapsulated key material is represented in the output as an EC point.</li>
+ * <li>The above symmetric key material is used by Data Encapsulation Mechanism (DEM) to encrypt the
+ * provided plaintext and authenticate the ciphertext. The resulting authenticated ciphertext is
+ * then output. When decrypting, the DEM first authenticates the ciphertext and, only if it
+ * authenticates, decrypts the ciphertext and outputs the plaintext.</li>
+ * </ol>
+ *
+ * <p>Details of KEM:
+ * <ul>
+ * <li>Only curves with cofactor of {@code 1} are supported.</li>
+ * <li>{@code CheckMode}, {@code OldCofactorMode}, {@code CofactorMode}, and {@code SingleHashMode}
+ * are {@code 0}.
+ * <li>Point format is specified by {@link #getKemPointFormat()}.</li>
+ * <li>KDF algorithm is specified by {@link #getKemKdfAlgorithm()}.</li>
+ * </ul>
+ *
+ * <p>Details of DEM:
+ * <ul>
+ * <li>Only DEM1-like mechanism is supported, with its symmetric cipher (SC) specified by
+ * {@link #getDemCipherTransformation()} (e.g., {@code AES/CBC/NoPadding} for standard DEM1) and
+ * MAC algorithm specified by {@link #getDemMacAlgorithm()} (e.g., {@code HmacSHA1} for standard
+ * DEM1).</li>
+ * </ul>
+ *
+ * @hide
+ */
+public class EcIesParameterSpec implements AlgorithmParameterSpec {
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {PointFormat.UNCOMPRESSED, PointFormat.COMPRESSED})
+    public @interface PointFormatEnum {}
+
+    /**
+     * Wire format of the EC point.
+     */
+    public static abstract class PointFormat {
+
+        private PointFormat() {}
+
+        /** Unspecified point format. */
+        public static final int UNSPECIFIED = -1;
+
+        /**
+         * Uncompressed point format: both coordinates are stored separately.
+         *
+         * <p>The wire format is byte {@code 0x04} followed by binary representation of the
+         * {@code x} coordinate followed by binary representation of the {@code y} coordinate. See
+         * {@code ISO 18033-2} section {@code 5.4.3}.
+         */
+        public static final int UNCOMPRESSED = 0;
+
+        /**
+         * Compressed point format: only one coordinate is stored.
+         *
+         * <p>The wire format is byte {@code 0x02} or {@code 0x03} (depending on the value of the
+         * stored coordinate) followed by the binary representation of the {@code x} coordinate.
+         * See {@code ISO 18033-2} section {@code 5.4.3}.
+         */
+        public static final int COMPRESSED = 1;
+    }
+
+    /**
+     * Default parameter spec: NIST P-256 curve (aka secp256r1 aka prime256v1), compressed point
+     * format, {@code HKDFwithSHA256}, DEM uses 128-bit AES GCM.
+     */
+    public static final EcIesParameterSpec DEFAULT = new EcIesParameterSpec(
+            "P-256",
+            PointFormat.COMPRESSED,
+            "HKDFwithSHA256",
+            "AES/GCM/NoPadding",
+            128,
+            null,
+            0);
+
+    private final String mKemCurveName;
+    private final @PointFormatEnum int mKemPointFormat;
+    private final String mKemKdfAlgorithm;
+    private final String mDemCipherTransformation;
+    private final int mDemCipherKeySize;
+    private final String mDemMacAlgorithm;
+    private final int mDemMacKeySize;
+
+    private EcIesParameterSpec(
+            String kemCurveName,
+            @PointFormatEnum int kemPointFormat,
+            String kemKdfAlgorithm,
+            String demCipherTransformation,
+            int demCipherKeySize,
+            String demMacAlgorithm,
+            int demMacKeySize) {
+        mKemCurveName = kemCurveName;
+        mKemPointFormat = kemPointFormat;
+        mKemKdfAlgorithm = kemKdfAlgorithm;
+        mDemCipherTransformation = demCipherTransformation;
+        mDemCipherKeySize = demCipherKeySize;
+        mDemMacAlgorithm = demMacAlgorithm;
+        mDemMacKeySize = demMacKeySize;
+    }
+
+    /**
+     * Returns KEM EC curve name (e.g., {@code secp256r1}) or {@code null} if not specified.
+     */
+    public String getKemCurveName() {
+        return mKemCurveName;
+    }
+
+    /**
+     * Returns KEM EC point wire format or {@link PointFormat#UNSPECIFIED} if not specified.
+     */
+    public @PointFormatEnum int getKemPointFormat() {
+        return mKemPointFormat;
+    }
+
+    /**
+     * Returns KEM KDF algorithm (e.g., {@code HKDFwithSHA256} or {@code KDF1withSHA1}) or
+     * {@code null} if not specified.
+     */
+    public String getKemKdfAlgorithm() {
+        return mKemKdfAlgorithm;
+    }
+
+    /**
+     * Returns DEM {@link Cipher} transformation (e.g., {@code AES/GCM/NoPadding} or
+     * {@code AES/CBC/PKCS7Padding}) or {@code null} if not specified.
+     *
+     * @see Cipher#getInstance(String)
+     * @see #getDemCipherKeySize()
+     */
+    public String getDemCipherTransformation() {
+        return mDemCipherTransformation;
+    }
+
+    /**
+     * Returns DEM {@link Cipher} key size in bits.
+     *
+     * @see #getDemCipherTransformation()
+     */
+    public int getDemCipherKeySize() {
+        return mDemCipherKeySize;
+    }
+
+    /**
+     * Returns DEM {@link Mac} algorithm (e.g., {@code HmacSHA256} or {@code HmacSHA1}) or
+     * {@code null} if not specified.
+     *
+     * @see Mac#getInstance(String)
+     * @see #getDemMacKeySize()
+     */
+    public String getDemMacAlgorithm() {
+        return mDemMacAlgorithm;
+    }
+
+    /**
+     * Returns DEM {@link Mac} key size in bits.
+     *
+     * @see #getDemCipherTransformation()
+     */
+    public int getDemMacKeySize() {
+        return mDemMacKeySize;
+    }
+
+    /**
+     * Builder of {@link EcIesParameterSpec}.
+     */
+    public static class Builder {
+        private String mKemCurveName;
+        private @PointFormatEnum int mKemPointFormat = PointFormat.UNSPECIFIED;
+        private String mKemKdfAlgorithm;
+        private String mDemCipherTransformation;
+        private int mDemCipherKeySize = 128;
+        private String mDemMacAlgorithm;
+        private int mDemMacKeySize = -1;
+
+        /**
+         * Sets KEM EC curve name. For example, {@code P-256} or {@code secp256r1}.
+         *
+         * <p>NOTE: Only curves with cofactor of {@code 1} are supported.
+         */
+        public Builder setKemCurveName(String name) {
+            mKemCurveName = name;
+            return this;
+        }
+
+        /**
+         * Sets KEM EC point wire format.
+         */
+        public Builder setKemPointFormat(@PointFormatEnum int pointFormat) {
+            mKemPointFormat = pointFormat;
+            return this;
+        }
+
+        /**
+         * Sets KEM KDF algorithm. For example, {@code HKDFwithSHA256}, {@code KDF2withSHA256}, or
+         * {@code KDF1withSHA1}.
+         */
+        public Builder setKemKdfAlgorithm(String algorithm) {
+            mKemKdfAlgorithm = algorithm;
+            return this;
+        }
+
+        /**
+         * Sets DEM {@link Cipher} transformation. For example, {@code AES/GCM/NoPadding},
+         * {@code AES/CBC/PKCS7Padding} or {@code AES/CTR/NoPadding}.
+         *
+         * @see Cipher#getInstance(String)
+         */
+        public Builder setDemCipherTransformation(String transformation) {
+            mDemCipherTransformation = transformation;
+            return this;
+        }
+
+        /**
+         * Returns DEM {@link Cipher} key size in bits.
+         *
+         * <p>The default value is {@code 128} bits.
+         *
+         * @see #setDemCipherTransformation(String)
+         */
+        public Builder setDemCipherKeySize(int sizeBits) {
+            mDemCipherKeySize = sizeBits;
+            return this;
+        }
+
+        /**
+         * Sets DEM {@link Mac} algorithm. For example, {@code HmacSHA256} or {@code HmacSHA1}.
+         *
+         * @see Mac#getInstance(String)
+         */
+        public Builder setDemMacAlgorithm(String algorithm) {
+            mDemMacAlgorithm = algorithm;
+            return this;
+        }
+
+        /**
+         * Sets DEM {@link Mac} key size in bits.
+         *
+         * <p>By default, {@code Mac} key size is the same as the {@code Cipher} key size.
+         *
+         * @see #setDemCipherKeySize(int)
+         */
+        public Builder setDemMacKeySize(int sizeBits) {
+            mDemMacKeySize = sizeBits;
+            return this;
+        }
+
+        /**
+         * Returns a new {@link EcIesParameterSpec} based on the current state of this builder.
+         */
+        public EcIesParameterSpec build() {
+            int demMacKeySize = (mDemMacKeySize != -1) ? mDemMacKeySize : mDemCipherKeySize;
+            return new EcIesParameterSpec(
+                    mKemCurveName,
+                    mKemPointFormat,
+                    mKemKdfAlgorithm,
+                    mDemCipherTransformation,
+                    mDemCipherKeySize,
+                    mDemMacAlgorithm,
+                    demMacKeySize
+                    );
+        }
+    }
+}
diff --git a/keystore/tests/src/android/security/KeyStoreTest.java b/keystore/tests/src/android/security/KeyStoreTest.java
index 6e3f8be..1a5552a 100644
--- a/keystore/tests/src/android/security/KeyStoreTest.java
+++ b/keystore/tests/src/android/security/KeyStoreTest.java
@@ -294,14 +294,14 @@
 
     public void testSaw_ungrantedUid_Bluetooth() throws Exception {
         String[] results1 = mKeyStore.saw(TEST_KEYNAME, Process.BLUETOOTH_UID);
-        assertNull(results1);
+        assertEquals(0, results1.length);
 
         mKeyStore.password(TEST_PASSWD);
         mKeyStore.put(TEST_KEYNAME1, TEST_KEYVALUE, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED);
         mKeyStore.put(TEST_KEYNAME2, TEST_KEYVALUE, KeyStore.UID_SELF, KeyStore.FLAG_ENCRYPTED);
 
         String[] results2 = mKeyStore.saw(TEST_KEYNAME, Process.BLUETOOTH_UID);
-        assertNull(results2);
+        assertEquals(0, results2.length);
     }
 
     public void testSaw_grantedUid_Wifi() throws Exception {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5494000..05a4d7e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -15709,8 +15709,9 @@
         }
 
         synchronized (this) {
-            if (callerApp != null && callerApp.pid == 0) {
-                // Caller already died
+            if (callerApp != null && (callerApp.thread == null
+                    || callerApp.thread.asBinder() != caller.asBinder())) {
+                // Original caller already died
                 return null;
             }
             ReceiverList rl