Merge "Update RS to use latest Clang-2812033 prebuilts as well."
diff --git a/core/clang/tidy.mk b/core/clang/tidy.mk
index e8a69ef..e61b878 100644
--- a/core/clang/tidy.mk
+++ b/core/clang/tidy.mk
@@ -29,10 +29,15 @@
 # where google-runtime-int is enabled at the end.
 DEFAULT_LOCAL_TIDY_CHECKS := \
   external/:,-google-build-using-namespace \
-  external/:,-google-explicit-constructor \
-  external/:,-google-runtime-int \
+  external/:,-google-explicit-constructor,-google-runtime-int \
   external/google:,google-runtime-int \
   external/webrtc/:,google-runtime-int \
+  hardware/qcom:,-google-build-using-namespace \
+  hardware/qcom:,-google-explicit-constructor,-google-runtime-int \
+  vendor/lge:,-google-build-using-namespace \
+  vendor/lge:,-google-explicit-constructor,-google-runtime-int \
+  vendor/widevine:,-google-build-using-namespace \
+  vendor/widevine:,-google-explicit-constructor,-google-runtime-int \
 
 # Returns 2nd word of $(1) if $(2) has prefix of the 1st word of $(1).
 define find_default_local_tidy_check2
diff --git a/core/soong.mk b/core/soong.mk
index 659a1ab..aaaa136 100644
--- a/core/soong.mk
+++ b/core/soong.mk
@@ -19,7 +19,7 @@
     SOONG_NEEDS_REBOOTSTRAP := FORCE
     $(warning soong_out_dir changed)
   endif
-  ifneq ($(strip $(shell build/soong/reverse_path.py $(SOONG_OUT_DIR))),$(strip $(shell source $(SOONG_BOOTSTRAP); echo $$SRCDIR_FROM_BUILDDIR)))
+  ifneq ($(strip $(shell build/soong/scripts/reverse_path.py $(SOONG_OUT_DIR))),$(strip $(shell source $(SOONG_BOOTSTRAP); echo $$SRCDIR_FROM_BUILDDIR)))
     SOONG_NEEDS_REBOOTSTRAP := FORCE
     $(warning reverse path changed)
   endif
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index d923c26..d0b077a 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -65,7 +65,9 @@
 
 CTS_TEST_JAR_LIST := \
 	cts-junit \
-	CtsJdwp
+	CtsJdwp \
+	cts-testng \
+	CtsLibcoreOj
 
 # Depend on the full package paths rather than the phony targets to avoid
 # rebuilding the packages every time.
diff --git a/tools/ijar/classfile.cc b/tools/ijar/classfile.cc
index e0cf42e..d33e0db 100644
--- a/tools/ijar/classfile.cc
+++ b/tools/ijar/classfile.cc
@@ -123,7 +123,7 @@
 // See sec.4.4 of JVM spec.
 struct Constant {
 
-  Constant(u1 tag) :
+  explicit Constant(u1 tag) :
       slot_(0),
       tag_(tag) {}
 
@@ -180,7 +180,7 @@
 // See sec.4.4.1 of JVM spec.
 struct Constant_Class : Constant
 {
-  Constant_Class(u2 name_index) :
+  explicit Constant_Class(u2 name_index) :
       Constant(CONSTANT_Class),
       name_index_(name_index) {}
 
@@ -231,7 +231,7 @@
 // See sec.4.4.3 of JVM spec.
 struct Constant_String : Constant
 {
-  Constant_String(u2 string_index) :
+  explicit Constant_String(u2 string_index) :
       Constant(CONSTANT_String),
       string_index_(string_index) {}
 
@@ -360,7 +360,7 @@
 // See sec.4.4.9 of JVM spec.
 struct Constant_MethodType : Constant
 {
-  Constant_MethodType(u2 descriptor_index) :
+  explicit Constant_MethodType(u2 descriptor_index) :
       Constant(CONSTANT_MethodType),
       descriptor_index_(descriptor_index) {}
 
diff --git a/tools/ijar/zip.cc b/tools/ijar/zip.cc
index ca5f396..3aa06db 100644
--- a/tools/ijar/zip.cc
+++ b/tools/ijar/zip.cc
@@ -846,6 +846,7 @@
   memcpy(entry->file_name, filename, file_name_length_);
   entry->extra_field_length = 0;
   entry->extra_field = (const u1 *)"";
+  entry->crc32 = 0;
 
   // Output the ZIP local_file_header:
   put_u4le(q, LOCAL_FILE_HEADER_SIGNATURE);
diff --git a/tools/signapk/src/com/android/signapk/SignApk.java b/tools/signapk/src/com/android/signapk/SignApk.java
index d763be5..69f17e2 100644
--- a/tools/signapk/src/com/android/signapk/SignApk.java
+++ b/tools/signapk/src/com/android/signapk/SignApk.java
@@ -132,10 +132,15 @@
     private static final int MIN_API_LEVEL_FOR_SHA256_JAR_SIGNATURES = 18;
 
     /**
-     * Return one of USE_SHA1 or USE_SHA256 according to the signature
-     * algorithm specified in the cert.
+     * Returns the digest algorithm ID (one of {@code USE_SHA1} or {@code USE_SHA256}) to be used
+     * for v1 signing (using JAR Signature Scheme) an APK using the private key corresponding to the
+     * provided certificate.
+     *
+     * @param minSdkVersion minimum Android platform API Level supported by the APK (see
+     *        minSdkVersion attribute in AndroidManifest.xml). The higher the minSdkVersion, the
+     *        stronger hash may be used for signing the APK.
      */
-    private static int getDigestAlgorithm(X509Certificate cert, int minSdkVersion) {
+    private static int getV1DigestAlgorithmForApk(X509Certificate cert, int minSdkVersion) {
         String sigAlg = cert.getSigAlgName().toUpperCase(Locale.US);
         if ("SHA1WITHRSA".equals(sigAlg) || "MD5WITHRSA".equals(sigAlg)) {
             // see "HISTORICAL NOTE" above.
@@ -152,20 +157,50 @@
         }
     }
 
-    /** Returns the expected signature algorithm for this key type. */
-    private static String getSignatureAlgorithm(X509Certificate cert, int minSdkVersion) {
-        String keyType = cert.getPublicKey().getAlgorithm().toUpperCase(Locale.US);
-        if ("RSA".equalsIgnoreCase(keyType)) {
-            if ((minSdkVersion >= MIN_API_LEVEL_FOR_SHA256_JAR_SIGNATURES)
-                    || (getDigestAlgorithm(cert, minSdkVersion) == USE_SHA256)) {
-                return "SHA256withRSA";
-            } else {
-                return "SHA1withRSA";
-            }
-        } else if ("EC".equalsIgnoreCase(keyType)) {
-            return "SHA256withECDSA";
+    /**
+     * Returns the digest algorithm ID (one of {@code USE_SHA1} or {@code USE_SHA256}) to be used
+     * for signing an OTA update package using the private key corresponding to the provided
+     * certificate.
+     */
+    private static int getDigestAlgorithmForOta(X509Certificate cert) {
+        String sigAlg = cert.getSigAlgName().toUpperCase(Locale.US);
+        if ("SHA1WITHRSA".equals(sigAlg) || "MD5WITHRSA".equals(sigAlg)) {
+            // see "HISTORICAL NOTE" above.
+            return USE_SHA1;
+        } else if (sigAlg.startsWith("SHA256WITH")) {
+            return USE_SHA256;
         } else {
-            throw new IllegalArgumentException("unsupported key type: " + keyType);
+            throw new IllegalArgumentException("unsupported signature algorithm \"" + sigAlg +
+                                               "\" in cert [" + cert.getSubjectDN());
+        }
+    }
+
+    /**
+     * Returns the JCA {@link java.security.Signature} algorithm to be used for signing and OTA
+     * or v1 signing an APK using the private key corresponding to the provided certificate and the
+     * provided digest algorithm (see {@code USE_SHA1} and {@code USE_SHA256} constants).
+     */
+    private static String getJcaSignatureAlgorithmForV1SigningOrOta(
+            X509Certificate cert, int hash) {
+        String sigAlgDigestPrefix;
+        switch (hash) {
+            case USE_SHA1:
+                sigAlgDigestPrefix = "SHA1";
+                break;
+            case USE_SHA256:
+                sigAlgDigestPrefix = "SHA256";
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown hash ID: " + hash);
+        }
+
+        String keyAlgorithm = cert.getPublicKey().getAlgorithm();
+        if ("RSA".equalsIgnoreCase(keyAlgorithm)) {
+            return sigAlgDigestPrefix + "withRSA";
+        } else if ("EC".equalsIgnoreCase(keyAlgorithm)) {
+            return sigAlgDigestPrefix + "withECDSA";
+        } else {
+            throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
         }
     }
 
@@ -483,7 +518,7 @@
 
     /** Sign data and write the digital signature to 'out'. */
     private static void writeSignatureBlock(
-        CMSTypedData data, X509Certificate publicKey, PrivateKey privateKey, int minSdkVersion,
+        CMSTypedData data, X509Certificate publicKey, PrivateKey privateKey, int hash,
         OutputStream out)
         throws IOException,
                CertificateEncodingException,
@@ -495,7 +530,8 @@
 
         CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
         ContentSigner signer =
-                new JcaContentSignerBuilder(getSignatureAlgorithm(publicKey, minSdkVersion))
+                new JcaContentSignerBuilder(
+                        getJcaSignatureAlgorithmForV1SigningOrOta(publicKey, hash))
                         .build(privateKey);
         gen.addSignerInfoGenerator(
             new JcaSignerInfoGeneratorBuilder(
@@ -686,21 +722,21 @@
         private final File publicKeyFile;
         private final X509Certificate publicKey;
         private final PrivateKey privateKey;
+        private final int hash;
         private final long timestamp;
-        private final int minSdkVersion;
         private final OutputStream outputStream;
         private final ASN1ObjectIdentifier type;
         private WholeFileSignerOutputStream signer;
 
         public CMSSigner(JarFile inputJar, File publicKeyFile,
-                         X509Certificate publicKey, PrivateKey privateKey, long timestamp,
-                         int minSdkVersion, OutputStream outputStream) {
+                         X509Certificate publicKey, PrivateKey privateKey, int hash,
+                         long timestamp, OutputStream outputStream) {
             this.inputJar = inputJar;
             this.publicKeyFile = publicKeyFile;
             this.publicKey = publicKey;
             this.privateKey = privateKey;
+            this.hash = hash;
             this.timestamp = timestamp;
-            this.minSdkVersion = minSdkVersion;
             this.outputStream = outputStream;
             this.type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
         }
@@ -725,8 +761,6 @@
                 signer = new WholeFileSignerOutputStream(out, outputStream);
                 JarOutputStream outputJar = new JarOutputStream(signer);
 
-                int hash = getDigestAlgorithm(publicKey, minSdkVersion);
-
                 Manifest manifest = addDigestsToManifest(inputJar, hash);
                 copyFiles(manifest, inputJar, outputJar, timestamp, 0);
                 addOtacert(outputJar, publicKeyFile, timestamp, manifest, hash);
@@ -734,8 +768,8 @@
                 signFile(manifest,
                          new X509Certificate[]{ publicKey },
                          new PrivateKey[]{ privateKey },
+                         new int[] { hash },
                          timestamp,
-                         minSdkVersion,
                          false, // Don't sign using APK Signature Scheme v2
                          outputJar);
 
@@ -753,7 +787,7 @@
                    CertificateEncodingException,
                    OperatorCreationException,
                    CMSException {
-            SignApk.writeSignatureBlock(this, publicKey, privateKey, minSdkVersion, temp);
+            SignApk.writeSignatureBlock(this, publicKey, privateKey, hash, temp);
         }
 
         public WholeFileSignerOutputStream getSigner() {
@@ -763,10 +797,10 @@
 
     private static void signWholeFile(JarFile inputJar, File publicKeyFile,
                                       X509Certificate publicKey, PrivateKey privateKey,
-                                      long timestamp, int minSdkVersion,
+                                      int hash, long timestamp,
                                       OutputStream outputStream) throws Exception {
         CMSSigner cmsOut = new CMSSigner(inputJar, publicKeyFile,
-                publicKey, privateKey, timestamp, minSdkVersion, outputStream);
+                publicKey, privateKey, hash, timestamp, outputStream);
 
         ByteArrayOutputStream temp = new ByteArrayOutputStream();
 
@@ -831,9 +865,8 @@
     }
 
     private static void signFile(Manifest manifest,
-                                 X509Certificate[] publicKey, PrivateKey[] privateKey,
+                                 X509Certificate[] publicKey, PrivateKey[] privateKey, int[] hash,
                                  long timestamp,
-                                 int minSdkVersion,
                                  boolean additionallySignedUsingAnApkSignatureScheme,
                                  JarOutputStream outputJar)
         throws Exception {
@@ -855,7 +888,7 @@
             writeSignatureFile(
                     manifest,
                     baos,
-                    getDigestAlgorithm(publicKey[k], minSdkVersion),
+                    hash[k],
                     additionallySignedUsingAnApkSignatureScheme);
             byte[] signedData = baos.toByteArray();
             outputJar.write(signedData);
@@ -868,7 +901,7 @@
             je.setTime(timestamp);
             outputJar.putNextEntry(je);
             writeSignatureBlock(new CMSProcessableByteArray(signedData),
-                                publicKey[k], privateKey[k], minSdkVersion, outputJar);
+                                publicKey[k], privateKey[k], hash[k], outputJar);
         }
     }
 
@@ -1075,7 +1108,6 @@
 
         JarFile inputJar = null;
         FileOutputStream outputFile = null;
-        int hashes = 0;
 
         try {
             File firstPublicKeyFile = new File(args[argstart+0]);
@@ -1085,7 +1117,6 @@
                 for (int i = 0; i < numKeys; ++i) {
                     int argNum = argstart + i*2;
                     publicKey[i] = readPublicKey(new File(args[argNum]));
-                    hashes |= getDigestAlgorithm(publicKey[i], minSdkVersion);
                 }
             } catch (IllegalArgumentException e) {
                 System.err.println(e);
@@ -1111,10 +1142,11 @@
             // NOTE: Signing currently recompresses any compressed entries using Deflate (default
             // compression level for OTA update files and maximum compession level for APKs).
             if (signWholeFile) {
-                SignApk.signWholeFile(inputJar, firstPublicKeyFile,
-                                      publicKey[0], privateKey[0],
-                                      timestamp, minSdkVersion,
-                                      outputFile);
+                int digestAlgorithm = getDigestAlgorithmForOta(publicKey[0]);
+                signWholeFile(inputJar, firstPublicKeyFile,
+                        publicKey[0], privateKey[0], digestAlgorithm,
+                        timestamp,
+                        outputFile);
             } else {
                 // Generate, in memory, an APK signed using standard JAR Signature Scheme.
                 ByteArrayOutputStream v1SignedApkBuf = new ByteArrayOutputStream();
@@ -1122,12 +1154,18 @@
                 // Use maximum compression for compressed entries because the APK lives forever on
                 // the system partition.
                 outputJar.setLevel(9);
-                Manifest manifest = addDigestsToManifest(inputJar, hashes);
+                int v1DigestAlgorithmBitSet = 0;
+                int[] v1DigestAlgorithm = new int[numKeys];
+                for (int i = 0; i < numKeys; ++i) {
+                    v1DigestAlgorithm[i] = getV1DigestAlgorithmForApk(publicKey[i], minSdkVersion);
+                    v1DigestAlgorithmBitSet |= v1DigestAlgorithm[i];
+                }
+                Manifest manifest = addDigestsToManifest(inputJar, v1DigestAlgorithmBitSet);
                 copyFiles(manifest, inputJar, outputJar, timestamp, alignment);
                 signFile(
                         manifest,
-                        publicKey, privateKey,
-                        timestamp, minSdkVersion, signUsingApkSignatureSchemeV2,
+                        publicKey, privateKey, v1DigestAlgorithm,
+                        timestamp, signUsingApkSignatureSchemeV2,
                         outputJar);
                 outputJar.close();
                 ByteBuffer v1SignedApk = ByteBuffer.wrap(v1SignedApkBuf.toByteArray());