Merge "Ensure there are no empty paths in ANDROID_BUILD_PATHS and PATH."
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 9f5a599..800dbbc 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -35,6 +35,10 @@
endif
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
+ifneq ($(strip $(LOCAL_MODULE_STEM)$(LOCAL_BUILT_MODULE_STEM)),)
+$(error $(LOCAL_PATH): Package modules may not define LOCAL_MODULE_STEM or LOCAL_BUILT_MODULE_STEM)
+endif
+
ifneq ($(strip $(LOCAL_MODULE)),)
$(error $(LOCAL_PATH): Package modules may not define LOCAL_MODULE)
endif
diff --git a/core/product_config.mk b/core/product_config.mk
index 614dfa2..cf92924 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -320,6 +320,12 @@
PRODUCT_SYSTEM_SERVER_JARS := $(call qualify-platform-jars,$(PRODUCT_SYSTEM_SERVER_JARS))
+# Sort APEX system server jars. We use deterministic alphabetical order when
+# constructing SYSTEMSERVERCLASSPATH definition on device after a Mainline
+# update. Enforce it in the build system as well to avoid recompiling everything
+# after an update due a change in SYSTEMSERVERCLASSPATH order.
+PRODUCT_APEX_SYSTEM_SERVER_JARS := $(sort $(PRODUCT_APEX_SYSTEM_SERVER_JARS))
+
ifndef PRODUCT_SYSTEM_NAME
PRODUCT_SYSTEM_NAME := $(PRODUCT_NAME)
endif
diff --git a/core/product_config.rbc b/core/product_config.rbc
index 9a6b1c0..c0bf281 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -220,13 +220,21 @@
return (globals, configs[top_pcm_name][1], globals_base)
+def _dictionary_difference(a, b):
+ result = {}
+ for attr, val in a.items():
+ if attr not in b or b[attr] != val:
+ result[attr] = val
+ return result
+
def _board_configuration(board_config_init, input_variables_init):
globals = {}
h = __h_new()
input_variables_init(globals, h)
+ cfg_base = dict(**h[0])
globals_base = dict(**globals)
board_config_init(globals, h)
- return (globals, h[1], globals_base)
+ return (globals, _dictionary_difference(h[0], cfg_base), globals_base)
def _substitute_inherited(configs, pcm_name, cfg):
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index e988d00..5e20218 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -65,7 +65,7 @@
com.android.tethering:framework-tethering \
com.android.wifi:framework-wifi
-# APEX system server jars. Keep the list sorted by module names and then library names.
+# APEX system server jars. The list will be sorted automatically.
PRODUCT_APEX_SYSTEM_SERVER_JARS := \
com.android.appsearch:service-appsearch \
com.android.art:service-art \
diff --git a/tools/signapk/src/com/android/signapk/SignApk.java b/tools/signapk/src/com/android/signapk/SignApk.java
index 8bf1005..232e119 100644
--- a/tools/signapk/src/com/android/signapk/SignApk.java
+++ b/tools/signapk/src/com/android/signapk/SignApk.java
@@ -64,12 +64,19 @@
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
import java.security.Key;
import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.KeyStore.PrivateKeyEntry;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
+import java.security.UnrecoverableEntryException;
+import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
@@ -286,6 +293,32 @@
}
}
+ private static KeyStore createKeyStore(String keyStoreName, String keyStorePin) throws
+ CertificateException,
+ IOException,
+ KeyStoreException,
+ NoSuchAlgorithmException {
+ KeyStore keyStore = KeyStore.getInstance(keyStoreName);
+ keyStore.load(null, keyStorePin == null ? null : keyStorePin.toCharArray());
+ return keyStore;
+ }
+
+ /** Get a PKCS#11 private key from keyStore */
+ private static PrivateKey loadPrivateKeyFromKeyStore(
+ final KeyStore keyStore, final String keyName, final String password)
+ throws CertificateException, KeyStoreException, NoSuchAlgorithmException,
+ UnrecoverableKeyException, UnrecoverableEntryException {
+ final Key key = keyStore.getKey(keyName, password == null ? null : password.toCharArray());
+ final PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) keyStore.getEntry(keyName, null);
+ if (privateKeyEntry == null) {
+ throw new Error(
+ "Key "
+ + keyName
+ + " not found in the token provided by PKCS11 library!");
+ }
+ return privateKeyEntry.getPrivateKey();
+ }
+
/**
* Add a copy of the public key to the archive; this should
* exactly match one of the files in
@@ -1022,6 +1055,8 @@
"[-a <alignment>] " +
"[--align-file-size] " +
"[-providerClass <className>] " +
+ "[-loadPrivateKeysFromKeyStore <keyStoreName>]" +
+ "[-keyStorePin <pin>]" +
"[--min-sdk-version <n>] " +
"[--disable-v2] " +
"[--enable-v4] " +
@@ -1044,6 +1079,8 @@
boolean signWholeFile = false;
String providerClass = null;
+ String keyStoreName = null;
+ String keyStorePin = null;
int alignment = 4;
boolean alignFileSize = false;
Integer minSdkVersionOverride = null;
@@ -1062,6 +1099,18 @@
}
providerClass = args[++argstart];
++argstart;
+ } else if ("-loadPrivateKeysFromKeyStore".equals(args[argstart])) {
+ if (argstart + 1 >= args.length) {
+ usage();
+ }
+ keyStoreName = args[++argstart];
+ ++argstart;
+ } else if ("-keyStorePin".equals(args[argstart])) {
+ if (argstart + 1 >= args.length) {
+ usage();
+ }
+ keyStorePin = args[++argstart];
+ ++argstart;
} else if ("-a".equals(args[argstart])) {
alignment = Integer.parseInt(args[++argstart]);
++argstart;
@@ -1142,11 +1191,21 @@
// timestamp using the current timezone. We thus adjust the milliseconds since epoch
// value to end up with MS-DOS timestamp of Jan 1 2009 00:00:00.
timestamp -= TimeZone.getDefault().getOffset(timestamp);
-
+ KeyStore keyStore = null;
+ if (keyStoreName != null) {
+ keyStore = createKeyStore(keyStoreName, keyStorePin);
+ }
PrivateKey[] privateKey = new PrivateKey[numKeys];
for (int i = 0; i < numKeys; ++i) {
int argNum = argstart + i*2 + 1;
- privateKey[i] = readPrivateKey(new File(args[argNum]));
+ if (keyStore == null) {
+ privateKey[i] = readPrivateKey(new File(args[argNum]));
+ } else {
+ String[] splits = args[argNum].split(":", 2);
+ final String keyAlias = splits[0];
+ final String password = splits.length > 1 ? splits[1] : null;
+ privateKey[i] = loadPrivateKeyFromKeyStore(keyStore, keyAlias, password);
+ }
}
inputJar = new JarFile(new File(inputFilename), false); // Don't verify.