Merge "Switch to Vista instead of Win2K."
diff --git a/core/definitions.mk b/core/definitions.mk
index 5fe126d..623f209 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -142,11 +142,27 @@
endef
###########################################################
+## Remove any makefiles that are being handled by soong
+###########################################################
+ifeq ($(USE_SOONG),true)
+define filter-soong-makefiles
+$(foreach mk,$(1),\
+ $(if $(wildcard $(patsubst %/Android.mk,%/Android.bp,$(mk))),\
+ $(info skipping $(mk) ...),\
+ $(mk)))
+endef
+else
+define filter-soong-makefiles
+$(1)
+endef
+endif
+
+###########################################################
## Retrieve a list of all makefiles immediately below some directory
###########################################################
define all-makefiles-under
-$(sort $(wildcard $(1)/*/Android.mk))
+$(sort $(call filter-soong-makefiles,$(wildcard $(1)/*/Android.mk)))
endef
###########################################################
@@ -157,8 +173,9 @@
# $(1): directory to search under
# Ignores $(1)/Android.mk
define first-makefiles-under
-$(shell build/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) \
- --mindepth=2 $(1) Android.mk)
+$(call filter-soong-makefiles,\
+ $(shell build/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) \
+ --mindepth=2 $(1) Android.mk))
endef
###########################################################
@@ -178,7 +195,8 @@
# $(1): List of directories to look for under this directory
define all-named-subdir-makefiles
-$(sort $(wildcard $(addsuffix /Android.mk, $(addprefix $(call my-dir)/,$(1)))))
+$(sort $(call filter-soong-makefiles,\
+ $(wildcard $(addsuffix /Android.mk, $(addprefix $(call my-dir)/,$(1))))))
endef
###########################################################
diff --git a/core/main.mk b/core/main.mk
index d2f8414..32b0b39 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -534,11 +534,12 @@
# --mindepth=2 makes the prunes not work.
subdir_makefiles := \
$(shell build/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) $(subdirs) Android.mk)
+
ifeq ($(USE_SOONG),true)
-subdir_makefiles := $(SOONG_ANDROID_MK) $(subdir_makefiles)
+subdir_makefiles := $(SOONG_ANDROID_MK) $(call filter-soong-makefiles,$(subdir_makefiles))
endif
-$(foreach mk, $(subdir_makefiles), $(info including $(mk) ...)$(eval include $(mk)))
+$(foreach mk, $(subdir_makefiles),$(info including $(mk) ...)$(eval include $(mk)))
endif # dont_bother
diff --git a/tools/makeparallel/makeparallel.cpp b/tools/makeparallel/makeparallel.cpp
index 576fe8d..cf125fa 100644
--- a/tools/makeparallel/makeparallel.cpp
+++ b/tools/makeparallel/makeparallel.cpp
@@ -343,7 +343,7 @@
// child
int ret = execvp(path, args.data());
if (ret < 0) {
- error(errno, errno, "exec failed");
+ error(errno, errno, "exec %s failed", path);
}
abort();
}
diff --git a/tools/signapk/src/com/android/signapk/SignApk.java b/tools/signapk/src/com/android/signapk/SignApk.java
index dd02b09..06a8d7f 100644
--- a/tools/signapk/src/com/android/signapk/SignApk.java
+++ b/tools/signapk/src/com/android/signapk/SignApk.java
@@ -67,6 +67,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
@@ -116,14 +117,24 @@
private static final int USE_SHA256 = 2;
/**
+ * Minimum Android SDK API Level which accepts JAR signatures which use SHA-256. Older platform
+ * versions accept only SHA-1 signatures.
+ */
+ 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.
*/
- private static int getDigestAlgorithm(X509Certificate cert) {
+ private static int getDigestAlgorithm(X509Certificate cert, int minSdkVersion) {
String sigAlg = cert.getSigAlgName().toUpperCase(Locale.US);
- if ("SHA1WITHRSA".equals(sigAlg) ||
- "MD5WITHRSA".equals(sigAlg)) { // see "HISTORICAL NOTE" above.
- return USE_SHA1;
+ if ("SHA1WITHRSA".equals(sigAlg) || "MD5WITHRSA".equals(sigAlg)) {
+ // see "HISTORICAL NOTE" above.
+ if (minSdkVersion < MIN_API_LEVEL_FOR_SHA256_JAR_SIGNATURES) {
+ return USE_SHA1;
+ } else {
+ return USE_SHA256;
+ }
} else if (sigAlg.startsWith("SHA256WITH")) {
return USE_SHA256;
} else {
@@ -133,10 +144,11 @@
}
/** Returns the expected signature algorithm for this key type. */
- private static String getSignatureAlgorithm(X509Certificate cert) {
+ private static String getSignatureAlgorithm(X509Certificate cert, int minSdkVersion) {
String keyType = cert.getPublicKey().getAlgorithm().toUpperCase(Locale.US);
if ("RSA".equalsIgnoreCase(keyType)) {
- if (getDigestAlgorithm(cert) == USE_SHA256) {
+ if ((minSdkVersion >= MIN_API_LEVEL_FOR_SHA256_JAR_SIGNATURES)
+ || (getDigestAlgorithm(cert, minSdkVersion) == USE_SHA256)) {
return "SHA256withRSA";
} else {
return "SHA1withRSA";
@@ -309,10 +321,24 @@
Attributes attr = null;
if (input != null) attr = input.getAttributes(name);
attr = attr != null ? new Attributes(attr) : new Attributes();
+ // Remove any previously computed digests from this entry's attributes.
+ for (Iterator<Object> i = attr.keySet().iterator(); i.hasNext();) {
+ Object key = i.next();
+ if (!(key instanceof Attributes.Name)) {
+ continue;
+ }
+ String attributeNameLowerCase =
+ ((Attributes.Name) key).toString().toLowerCase(Locale.US);
+ if (attributeNameLowerCase.endsWith("-digest")) {
+ i.remove();
+ }
+ }
+ // Add SHA-1 digest if requested
if (md_sha1 != null) {
attr.putValue("SHA1-Digest",
new String(Base64.encode(md_sha1.digest()), "ASCII"));
}
+ // Add SHA-256 digest if requested
if (md_sha256 != null) {
attr.putValue("SHA-256-Digest",
new String(Base64.encode(md_sha256.digest()), "ASCII"));
@@ -438,7 +464,7 @@
/** Sign data and write the digital signature to 'out'. */
private static void writeSignatureBlock(
- CMSTypedData data, X509Certificate publicKey, PrivateKey privateKey,
+ CMSTypedData data, X509Certificate publicKey, PrivateKey privateKey, int minSdkVersion,
OutputStream out)
throws IOException,
CertificateEncodingException,
@@ -449,8 +475,9 @@
JcaCertStore certs = new JcaCertStore(certList);
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
- ContentSigner signer = new JcaContentSignerBuilder(getSignatureAlgorithm(publicKey))
- .build(privateKey);
+ ContentSigner signer =
+ new JcaContentSignerBuilder(getSignatureAlgorithm(publicKey, minSdkVersion))
+ .build(privateKey);
gen.addSignerInfoGenerator(
new JcaSignerInfoGeneratorBuilder(
new JcaDigestCalculatorProviderBuilder()
@@ -631,21 +658,23 @@
}
private static class CMSSigner implements CMSTypedData {
- private JarFile inputJar;
- private File publicKeyFile;
- private X509Certificate publicKey;
- private PrivateKey privateKey;
- private OutputStream outputStream;
+ private final JarFile inputJar;
+ private final File publicKeyFile;
+ private final X509Certificate publicKey;
+ private final PrivateKey privateKey;
+ 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,
+ X509Certificate publicKey, PrivateKey privateKey, int minSdkVersion,
OutputStream outputStream) {
this.inputJar = inputJar;
this.publicKeyFile = publicKeyFile;
this.publicKey = publicKey;
this.privateKey = privateKey;
+ this.minSdkVersion = minSdkVersion;
this.outputStream = outputStream;
this.type = new ASN1ObjectIdentifier(CMSObjectIdentifiers.data.getId());
}
@@ -670,7 +699,7 @@
signer = new WholeFileSignerOutputStream(out, outputStream);
JarOutputStream outputJar = new JarOutputStream(signer);
- int hash = getDigestAlgorithm(publicKey);
+ int hash = getDigestAlgorithm(publicKey, minSdkVersion);
// Assume the certificate is valid for at least an hour.
long timestamp = publicKey.getNotBefore().getTime() + 3600L * 1000;
@@ -682,6 +711,7 @@
signFile(manifest,
new X509Certificate[]{ publicKey },
new PrivateKey[]{ privateKey },
+ minSdkVersion,
outputJar);
signer.notifyClosing();
@@ -698,7 +728,7 @@
CertificateEncodingException,
OperatorCreationException,
CMSException {
- SignApk.writeSignatureBlock(this, publicKey, privateKey, temp);
+ SignApk.writeSignatureBlock(this, publicKey, privateKey, minSdkVersion, temp);
}
public WholeFileSignerOutputStream getSigner() {
@@ -708,9 +738,10 @@
private static void signWholeFile(JarFile inputJar, File publicKeyFile,
X509Certificate publicKey, PrivateKey privateKey,
+ int minSdkVersion,
OutputStream outputStream) throws Exception {
CMSSigner cmsOut = new CMSSigner(inputJar, publicKeyFile,
- publicKey, privateKey, outputStream);
+ publicKey, privateKey, minSdkVersion, outputStream);
ByteArrayOutputStream temp = new ByteArrayOutputStream();
@@ -776,6 +807,7 @@
private static void signFile(Manifest manifest,
X509Certificate[] publicKey, PrivateKey[] privateKey,
+ int minSdkVersion,
JarOutputStream outputJar)
throws Exception {
// Assume the certificate is valid for at least an hour.
@@ -795,7 +827,7 @@
je.setTime(timestamp);
outputJar.putNextEntry(je);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
- writeSignatureFile(manifest, baos, getDigestAlgorithm(publicKey[k]));
+ writeSignatureFile(manifest, baos, getDigestAlgorithm(publicKey[k], minSdkVersion));
byte[] signedData = baos.toByteArray();
outputJar.write(signedData);
@@ -807,7 +839,7 @@
je.setTime(timestamp);
outputJar.putNextEntry(je);
writeSignatureBlock(new CMSProcessableByteArray(signedData),
- publicKey[k], privateKey[k], outputJar);
+ publicKey[k], privateKey[k], minSdkVersion, outputJar);
}
}
@@ -887,6 +919,7 @@
boolean signWholeFile = false;
String providerClass = null;
int alignment = 4;
+ int minSdkVersion = 0;
int argstart = 0;
while (argstart < args.length && args[argstart].startsWith("-")) {
@@ -902,6 +935,15 @@
} else if ("-a".equals(args[argstart])) {
alignment = Integer.parseInt(args[++argstart]);
++argstart;
+ } else if ("--min-sdk-version".equals(args[argstart])) {
+ String minSdkVersionString = args[++argstart];
+ try {
+ minSdkVersion = Integer.parseInt(minSdkVersionString);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(
+ "min-sdk-version must be a decimal number: " + minSdkVersionString);
+ }
+ ++argstart;
} else {
usage();
}
@@ -931,7 +973,7 @@
for (int i = 0; i < numKeys; ++i) {
int argNum = argstart + i*2;
publicKey[i] = readPublicKey(new File(args[argNum]));
- hashes |= getDigestAlgorithm(publicKey[i]);
+ hashes |= getDigestAlgorithm(publicKey[i], minSdkVersion);
}
} catch (IllegalArgumentException e) {
System.err.println(e);
@@ -955,7 +997,7 @@
if (signWholeFile) {
SignApk.signWholeFile(inputJar, firstPublicKeyFile,
- publicKey[0], privateKey[0], outputFile);
+ publicKey[0], privateKey[0], minSdkVersion, outputFile);
} else {
JarOutputStream outputJar = new JarOutputStream(outputFile);
@@ -969,7 +1011,7 @@
Manifest manifest = addDigestsToManifest(inputJar, hashes);
copyFiles(manifest, inputJar, outputJar, timestamp, alignment);
- signFile(manifest, publicKey, privateKey, outputJar);
+ signFile(manifest, publicKey, privateKey, minSdkVersion, outputJar);
outputJar.close();
}
} catch (Exception e) {