Merge "Add PRODUCT_AVF_KERNEL_MODULES_ENABLED"
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 65e80fb..c61c653 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -1005,6 +1005,9 @@
ALL_MODULES.$(my_register_name).SHARED_LIBS := \
$(ALL_MODULES.$(my_register_name).SHARED_LIBS) $(LOCAL_SHARED_LIBRARIES)
+ALL_MODULES.$(my_register_name).STATIC_LIBS := \
+ $(ALL_MODULES.$(my_register_name).STATIC_LIBS) $(LOCAL_STATIC_LIBRARIES)
+
ALL_MODULES.$(my_register_name).SYSTEM_SHARED_LIBS := \
$(ALL_MODULES.$(my_register_name).SYSTEM_SHARED_LIBS) $(LOCAL_SYSTEM_SHARED_LIBRARIES)
@@ -1234,4 +1237,4 @@
###########################################################
## SBOM generation
###########################################################
-include $(BUILD_SBOM_GEN)
\ No newline at end of file
+include $(BUILD_SBOM_GEN)
diff --git a/core/config.mk b/core/config.mk
index 5457fd2..c549296 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -43,6 +43,8 @@
CHANGES_URL := https://android.googlesource.com/platform/build/+/master/Changes.md
.KATI_READONLY := CHANGES_URL
$(KATI_deprecated_var TARGET_USES_64_BIT_BINDER,All devices use 64-bit binder by default now. Uses of TARGET_USES_64_BIT_BINDER should be removed.)
+$(KATI_deprecated_var PRODUCT_SEPOLICY_SPLIT,All devices are built with split sepolicy.)
+$(KATI_deprecated_var PRODUCT_SEPOLICY_SPLIT_OVERRIDE,All devices are built with split sepolicy.)
$(KATI_obsolete_var PATH,Do not use PATH directly. See $(CHANGES_URL)#PATH)
$(KATI_obsolete_var PYTHONPATH,Do not use PYTHONPATH directly. See $(CHANGES_URL)#PYTHONPATH)
$(KATI_obsolete_var OUT,Use OUT_DIR instead. See $(CHANGES_URL)#OUT)
@@ -739,7 +741,6 @@
requirements := \
PRODUCT_TREBLE_LINKER_NAMESPACES \
- PRODUCT_SEPOLICY_SPLIT \
PRODUCT_ENFORCE_VINTF_MANIFEST \
PRODUCT_NOTICE_SPLIT
@@ -754,14 +755,6 @@
PRODUCT_FULL_TREBLE_OVERRIDE ?=
$(foreach req,$(requirements),$(eval $(req)_OVERRIDE ?=))
-ifneq ($(PRODUCT_SEPOLICY_SPLIT),true)
-# WARNING: DO NOT CHANGE: if you are downstream of AOSP, and you change this, without
-# letting upstream know it's important to you, we may do cleanup which breaks this
-# significantly. Please let us know if you are changing this.
-# TODO(b/257176017) - unsplit sepolicy is no longer supported
-PRODUCT_SEPOLICY_SPLIT := true
-endif
-
# TODO(b/114488870): disallow PRODUCT_FULL_TREBLE_OVERRIDE from being used.
.KATI_READONLY := \
PRODUCT_FULL_TREBLE_OVERRIDE \
@@ -1267,6 +1260,9 @@
.KATI_READONLY := JAVAC_NINJA_POOL R8_NINJA_POOL D8_NINJA_POOL
+# Soong modules that are known to have broken optional_uses_libs dependencies.
+BUILD_WARNING_BAD_OPTIONAL_USES_LIBS_ALLOWLIST := LegacyCamera Gallery2
+
# These goals don't need to collect and include Android.mks/CleanSpec.mks
# in the source tree.
dont_bother_goals := out product-graph
diff --git a/core/main.mk b/core/main.mk
index 2281b7a..40e690d 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -180,9 +180,7 @@
ADDITIONAL_SYSTEM_PROPERTIES += ro.treble.enabled=${PRODUCT_FULL_TREBLE}
$(KATI_obsolete_var PRODUCT_FULL_TREBLE,\
- Code should be written to work regardless of a device being Treble or \
- variables like PRODUCT_SEPOLICY_SPLIT should be used until that is \
- possible.)
+ Code should be written to work regardless of a device being Treble)
# Sets ro.actionable_compatible_property.enabled to know on runtime whether the
# allowed list of actionable compatible properties is enabled or not.
diff --git a/core/soong_config.mk b/core/soong_config.mk
index 46f06f7..6383393 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -294,14 +294,14 @@
$(call add_json_bool, BuildBrokenVendorPropertyNamespace, $(filter true,$(BUILD_BROKEN_VENDOR_PROPERTY_NAMESPACE)))
$(call add_json_list, BuildBrokenInputDirModules, $(BUILD_BROKEN_INPUT_DIR_MODULES))
+$(call add_json_list, BuildWarningBadOptionalUsesLibsAllowlist, $(BUILD_WARNING_BAD_OPTIONAL_USES_LIBS_ALLOWLIST))
+
$(call add_json_bool, BuildDebugfsRestrictionsEnabled, $(filter true,$(PRODUCT_SET_DEBUGFS_RESTRICTIONS)))
$(call add_json_bool, RequiresInsecureExecmemForSwiftshader, $(filter true,$(PRODUCT_REQUIRES_INSECURE_EXECMEM_FOR_SWIFTSHADER)))
$(call add_json_bool, SelinuxIgnoreNeverallows, $(filter true,$(SELINUX_IGNORE_NEVERALLOWS)))
-$(call add_json_bool, SepolicySplit, $(filter true,$(PRODUCT_SEPOLICY_SPLIT)))
-
$(call add_json_list, SepolicyFreezeTestExtraDirs, $(SEPOLICY_FREEZE_TEST_EXTRA_DIRS))
$(call add_json_list, SepolicyFreezeTestExtraPrebuiltDirs, $(SEPOLICY_FREEZE_TEST_EXTRA_PREBUILT_DIRS))
diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk
index e83d408..66ba8f1 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -18,6 +18,7 @@
'"test_config": [$(foreach w,$(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)),"$(w)", )], ' \
'"dependencies": [$(foreach w,$(sort $(ALL_DEPS.$(m).ALL_DEPS)),"$(w)", )], ' \
'"shared_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SHARED_LIBS)),"$(w)", )], ' \
+ '"static_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).STATIC_LIBS)),"$(w)", )], ' \
'"system_shared_libs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SYSTEM_SHARED_LIBS)),"$(w)", )], ' \
'"srcs": [$(foreach w,$(sort $(ALL_MODULES.$(m).SRCS)),"$(w)", )], ' \
'"srcjars": [$(foreach w,$(sort $(ALL_MODULES.$(m).SRCJARS)),"$(w)", )], ' \
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index 41233b2..d965367 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -27,6 +27,7 @@
$(call inherit-product-if-exists, external/google-fonts/source-sans-pro/fonts.mk)
$(call inherit-product-if-exists, external/noto-fonts/fonts.mk)
$(call inherit-product-if-exists, external/roboto-fonts/fonts.mk)
+$(call inherit-product-if-exists, external/roboto-flex-fonts/fonts.mk)
$(call inherit-product-if-exists, external/hyphenation-patterns/patterns.mk)
$(call inherit-product-if-exists, frameworks/base/data/keyboards/keyboards.mk)
$(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk)
diff --git a/tools/aconfig/src/cache.rs b/tools/aconfig/src/cache.rs
index 44ad3dd..972ba41 100644
--- a/tools/aconfig/src/cache.rs
+++ b/tools/aconfig/src/cache.rs
@@ -179,7 +179,6 @@
#[cfg(test)]
mod tests {
use super::*;
- use crate::aconfig::{FlagState, Permission};
#[test]
fn test_add_flag_declaration() {
diff --git a/tools/aconfig/src/codegen_rust.rs b/tools/aconfig/src/codegen_rust.rs
index fe4231b..a48e464 100644
--- a/tools/aconfig/src/codegen_rust.rs
+++ b/tools/aconfig/src/codegen_rust.rs
@@ -79,28 +79,10 @@
#[cfg(test)]
mod tests {
use super::*;
- use crate::commands::{create_cache, Input, Source};
#[test]
fn test_generate_rust_code() {
- let cache = create_cache(
- "test",
- vec![Input {
- source: Source::File("testdata/test.aconfig".to_string()),
- reader: Box::new(include_bytes!("../testdata/test.aconfig").as_slice()),
- }],
- vec![
- Input {
- source: Source::File("testdata/first.values".to_string()),
- reader: Box::new(include_bytes!("../testdata/first.values").as_slice()),
- },
- Input {
- source: Source::File("testdata/test.aconfig".to_string()),
- reader: Box::new(include_bytes!("../testdata/second.values").as_slice()),
- },
- ],
- )
- .unwrap();
+ let cache = crate::test::create_cache();
let generated = generate_rust_code(&cache).unwrap();
assert_eq!("src/lib.rs", format!("{}", generated.path.display()));
let expected = r#"
diff --git a/tools/aconfig/src/commands.rs b/tools/aconfig/src/commands.rs
index cce1d7f..3ae72c6 100644
--- a/tools/aconfig/src/commands.rs
+++ b/tools/aconfig/src/commands.rs
@@ -22,8 +22,8 @@
use std::io::Read;
use std::path::PathBuf;
-use crate::aconfig::{FlagDeclarations, FlagValue};
-use crate::cache::{Cache, CacheBuilder};
+use crate::aconfig::{FlagDeclarations, FlagState, FlagValue, Permission};
+use crate::cache::{Cache, CacheBuilder, Item};
use crate::codegen_cpp::generate_cpp_code;
use crate::codegen_java::generate_java_code;
use crate::codegen_rust::generate_rust_code;
@@ -93,16 +93,52 @@
Ok(builder.build())
}
-pub fn create_java_lib(cache: &Cache) -> Result<OutputFile> {
- generate_java_code(cache)
+pub fn create_java_lib(cache: Cache) -> Result<OutputFile> {
+ generate_java_code(&cache)
}
-pub fn create_cpp_lib(cache: &Cache) -> Result<OutputFile> {
- generate_cpp_code(cache)
+pub fn create_cpp_lib(cache: Cache) -> Result<OutputFile> {
+ generate_cpp_code(&cache)
}
-pub fn create_rust_lib(cache: &Cache) -> Result<OutputFile> {
- generate_rust_code(cache)
+pub fn create_rust_lib(cache: Cache) -> Result<OutputFile> {
+ generate_rust_code(&cache)
+}
+
+pub fn create_device_config_defaults(caches: Vec<Cache>) -> Result<Vec<u8>> {
+ let mut output = Vec::new();
+ for item in sort_and_iter_items(caches).filter(|item| item.permission == Permission::ReadWrite)
+ {
+ let line = format!(
+ "{}/{}:{}\n",
+ item.namespace,
+ item.name,
+ match item.state {
+ FlagState::Enabled => "enabled",
+ FlagState::Disabled => "disabled",
+ }
+ );
+ output.extend_from_slice(line.as_bytes());
+ }
+ Ok(output)
+}
+
+pub fn create_device_config_sysprops(caches: Vec<Cache>) -> Result<Vec<u8>> {
+ let mut output = Vec::new();
+ for item in sort_and_iter_items(caches).filter(|item| item.permission == Permission::ReadWrite)
+ {
+ let line = format!(
+ "persist.device_config.{}.{}={}\n",
+ item.namespace,
+ item.name,
+ match item.state {
+ FlagState::Enabled => "true",
+ FlagState::Disabled => "false",
+ }
+ );
+ output.extend_from_slice(line.as_bytes());
+ }
+ Ok(output)
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
@@ -112,29 +148,26 @@
Protobuf,
}
-pub fn dump_cache(mut caches: Vec<Cache>, format: DumpFormat) -> Result<Vec<u8>> {
+pub fn dump_cache(caches: Vec<Cache>, format: DumpFormat) -> Result<Vec<u8>> {
let mut output = Vec::new();
- caches.sort_by_cached_key(|cache| cache.namespace().to_string());
- for cache in caches.into_iter() {
- match format {
- DumpFormat::Text => {
- let mut lines = vec![];
- for item in cache.iter() {
- lines.push(format!(
- "{}/{}: {:?} {:?}\n",
- item.namespace, item.name, item.state, item.permission
- ));
- }
- output.append(&mut lines.concat().into());
+ match format {
+ DumpFormat::Text => {
+ for item in sort_and_iter_items(caches) {
+ let line = format!(
+ "{}/{}: {:?} {:?}\n",
+ item.namespace, item.name, item.state, item.permission
+ );
+ output.extend_from_slice(line.as_bytes());
}
- DumpFormat::Debug => {
- let mut lines = vec![];
- for item in cache.iter() {
- lines.push(format!("{:#?}\n", item));
- }
- output.append(&mut lines.concat().into());
+ }
+ DumpFormat::Debug => {
+ for item in sort_and_iter_items(caches) {
+ let line = format!("{:#?}\n", item);
+ output.extend_from_slice(line.as_bytes());
}
- DumpFormat::Protobuf => {
+ }
+ DumpFormat::Protobuf => {
+ for cache in sort_and_iter_caches(caches) {
let parsed_flags: ProtoParsedFlags = cache.into();
parsed_flags.write_to_vec(&mut output)?;
}
@@ -143,6 +176,15 @@
Ok(output)
}
+fn sort_and_iter_items(caches: Vec<Cache>) -> impl Iterator<Item = Item> {
+ sort_and_iter_caches(caches).flat_map(|cache| cache.into_iter())
+}
+
+fn sort_and_iter_caches(mut caches: Vec<Cache>) -> impl Iterator<Item = Cache> {
+ caches.sort_by_cached_key(|cache| cache.namespace().to_string());
+ caches.into_iter()
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -203,6 +245,22 @@
}
#[test]
+ fn test_create_device_config_defaults() {
+ let caches = vec![crate::test::create_cache()];
+ let bytes = create_device_config_defaults(caches).unwrap();
+ let text = std::str::from_utf8(&bytes).unwrap();
+ assert_eq!("test/disabled_rw:disabled\ntest/enabled_rw:enabled\n", text);
+ }
+
+ #[test]
+ fn test_create_device_config_sysprops() {
+ let caches = vec![crate::test::create_cache()];
+ let bytes = create_device_config_sysprops(caches).unwrap();
+ let text = std::str::from_utf8(&bytes).unwrap();
+ assert_eq!("persist.device_config.test.disabled_rw=false\npersist.device_config.test.enabled_rw=true\n", text);
+ }
+
+ #[test]
fn test_dump_text_format() {
let caches = vec![create_test_cache_ns1()];
let bytes = dump_cache(caches, DumpFormat::Text).unwrap();
diff --git a/tools/aconfig/src/main.rs b/tools/aconfig/src/main.rs
index 1d2ec95..dab0191 100644
--- a/tools/aconfig/src/main.rs
+++ b/tools/aconfig/src/main.rs
@@ -33,6 +33,9 @@
mod commands;
mod protos;
+#[cfg(test)]
+mod test;
+
use crate::cache::Cache;
use commands::{DumpFormat, Input, OutputFile, Source};
@@ -62,6 +65,16 @@
.arg(Arg::new("out").long("out").required(true)),
)
.subcommand(
+ Command::new("create-device-config-defaults")
+ .arg(Arg::new("cache").long("cache").action(ArgAction::Append).required(true))
+ .arg(Arg::new("out").long("out").default_value("-")),
+ )
+ .subcommand(
+ Command::new("create-device-config-sysprops")
+ .arg(Arg::new("cache").long("cache").action(ArgAction::Append).required(true))
+ .arg(Arg::new("out").long("out").default_value("-")),
+ )
+ .subcommand(
Command::new("dump")
.arg(Arg::new("cache").long("cache").action(ArgAction::Append).required(true))
.arg(
@@ -108,6 +121,15 @@
Ok(())
}
+fn write_output_to_file_or_stdout(path: &str, data: &[u8]) -> Result<()> {
+ if path == "-" {
+ io::stdout().write_all(data)?;
+ } else {
+ fs::File::create(path)?.write_all(data)?;
+ }
+ Ok(())
+}
+
fn main() -> Result<()> {
let matches = cli().get_matches();
match matches.subcommand() {
@@ -125,7 +147,7 @@
let file = fs::File::open(path)?;
let cache = Cache::read_from_reader(file)?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
- let generated_file = commands::create_java_lib(&cache)?;
+ let generated_file = commands::create_java_lib(cache)?;
write_output_file_realtive_to_dir(&dir, &generated_file)?;
}
Some(("create-cpp-lib", sub_matches)) => {
@@ -133,7 +155,7 @@
let file = fs::File::open(path)?;
let cache = Cache::read_from_reader(file)?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
- let generated_file = commands::create_cpp_lib(&cache)?;
+ let generated_file = commands::create_cpp_lib(cache)?;
write_output_file_realtive_to_dir(&dir, &generated_file)?;
}
Some(("create-rust-lib", sub_matches)) => {
@@ -141,9 +163,31 @@
let file = fs::File::open(path)?;
let cache = Cache::read_from_reader(file)?;
let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
- let generated_file = commands::create_rust_lib(&cache)?;
+ let generated_file = commands::create_rust_lib(cache)?;
write_output_file_realtive_to_dir(&dir, &generated_file)?;
}
+ Some(("create-device-config-defaults", sub_matches)) => {
+ let mut caches = Vec::new();
+ for path in sub_matches.get_many::<String>("cache").unwrap_or_default() {
+ let file = fs::File::open(path)?;
+ let cache = Cache::read_from_reader(file)?;
+ caches.push(cache);
+ }
+ let output = commands::create_device_config_defaults(caches)?;
+ let path = get_required_arg::<String>(sub_matches, "out")?;
+ write_output_to_file_or_stdout(path, &output)?;
+ }
+ Some(("create-device-config-sysprops", sub_matches)) => {
+ let mut caches = Vec::new();
+ for path in sub_matches.get_many::<String>("cache").unwrap_or_default() {
+ let file = fs::File::open(path)?;
+ let cache = Cache::read_from_reader(file)?;
+ caches.push(cache);
+ }
+ let output = commands::create_device_config_sysprops(caches)?;
+ let path = get_required_arg::<String>(sub_matches, "out")?;
+ write_output_to_file_or_stdout(path, &output)?;
+ }
Some(("dump", sub_matches)) => {
let mut caches = Vec::new();
for path in sub_matches.get_many::<String>("cache").unwrap_or_default() {
@@ -154,12 +198,7 @@
let format = get_required_arg::<DumpFormat>(sub_matches, "format")?;
let output = commands::dump_cache(caches, *format)?;
let path = get_required_arg::<String>(sub_matches, "out")?;
- let mut file: Box<dyn Write> = if *path == "-" {
- Box::new(io::stdout())
- } else {
- Box::new(fs::File::create(path)?)
- };
- file.write_all(&output)?;
+ write_output_to_file_or_stdout(path, &output)?;
}
_ => unreachable!(),
}
diff --git a/tools/aconfig/src/test.rs b/tools/aconfig/src/test.rs
new file mode 100644
index 0000000..621381a
--- /dev/null
+++ b/tools/aconfig/src/test.rs
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+#[cfg(test)]
+pub mod test_utils {
+ use crate::cache::Cache;
+ use crate::commands::{Input, Source};
+
+ pub fn create_cache() -> Cache {
+ crate::commands::create_cache(
+ "test",
+ vec![Input {
+ source: Source::File("testdata/test.aconfig".to_string()),
+ reader: Box::new(include_bytes!("../testdata/test.aconfig").as_slice()),
+ }],
+ vec![
+ Input {
+ source: Source::File("testdata/first.values".to_string()),
+ reader: Box::new(include_bytes!("../testdata/first.values").as_slice()),
+ },
+ Input {
+ source: Source::File("testdata/test.aconfig".to_string()),
+ reader: Box::new(include_bytes!("../testdata/second.values").as_slice()),
+ },
+ ],
+ )
+ .unwrap()
+ }
+}
+
+#[cfg(test)]
+pub use test_utils::*;
diff --git a/tools/compliance/cmd/sbom/sbom.go b/tools/compliance/cmd/sbom/sbom.go
index f61289e..a53741f 100644
--- a/tools/compliance/cmd/sbom/sbom.go
+++ b/tools/compliance/cmd/sbom/sbom.go
@@ -35,7 +35,7 @@
"github.com/google/blueprint/deptools"
"github.com/spdx/tools-golang/builder/builder2v2"
- "github.com/spdx/tools-golang/json"
+ spdx_json "github.com/spdx/tools-golang/json"
"github.com/spdx/tools-golang/spdx/common"
spdx "github.com/spdx/tools-golang/spdx/v2_2"
"github.com/spdx/tools-golang/spdxlib"
@@ -274,7 +274,7 @@
tn *compliance.TargetNode) (*projectmetadata.ProjectMetadata, error) {
pms, err := pmix.MetadataForProjects(tn.Projects()...)
if err != nil {
- return nil, fmt.Errorf("Unable to read projects for %q: %w\n", tn, err)
+ return nil, fmt.Errorf("Unable to read projects for %q: %w\n", tn.Name(), err)
}
if len(pms) == 0 {
return nil, nil
diff --git a/tools/compliance/cmd/sbom/sbom_test.go b/tools/compliance/cmd/sbom/sbom_test.go
index 8a62713..13ba66d 100644
--- a/tools/compliance/cmd/sbom/sbom_test.go
+++ b/tools/compliance/cmd/sbom/sbom_test.go
@@ -25,6 +25,7 @@
"time"
"android/soong/tools/compliance"
+
"github.com/spdx/tools-golang/builder/builder2v2"
"github.com/spdx/tools-golang/spdx/common"
spdx "github.com/spdx/tools-golang/spdx/v2_2"
@@ -2375,8 +2376,8 @@
if doc.DocumentName == "" {
return fmt.Errorf("DocumentName: got nothing, want Document Name")
}
- if fmt.Sprintf("%v", doc.CreationInfo.Creators[1].Creator) != "Google LLC" {
- return fmt.Errorf("Creator: got %v, want 'Google LLC'")
+ if c := fmt.Sprintf("%v", doc.CreationInfo.Creators[1].Creator); c != "Google LLC" {
+ return fmt.Errorf("Creator: got %v, want 'Google LLC'", c)
}
_, err := time.Parse(time.RFC3339, doc.CreationInfo.Created)
if err != nil {
diff --git a/tools/compliance/go.mod b/tools/compliance/go.mod
index 088915a..1928189 100644
--- a/tools/compliance/go.mod
+++ b/tools/compliance/go.mod
@@ -7,8 +7,11 @@
require (
android/soong v0.0.0
github.com/google/blueprint v0.0.0
+ github.com/spdx/tools-golang v0.0.0
)
+replace github.com/spdx/tools-golang v0.0.0 => ../../../../external/spdx-tools
+
require golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
replace android/soong v0.0.0 => ../../../soong
diff --git a/tools/find_static_candidates.py b/tools/find_static_candidates.py
new file mode 100644
index 0000000..7511b36
--- /dev/null
+++ b/tools/find_static_candidates.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python3
+
+"""Tool to find static libraries that maybe should be shared libraries and shared libraries that maybe should be static libraries.
+
+This tool only looks at the module-info.json for the current target.
+
+Example of "class" types for each of the modules in module-info.json
+ "EXECUTABLES": 2307,
+ "ETC": 9094,
+ "NATIVE_TESTS": 10461,
+ "APPS": 2885,
+ "JAVA_LIBRARIES": 5205,
+ "EXECUTABLES/JAVA_LIBRARIES": 119,
+ "FAKE": 553,
+ "SHARED_LIBRARIES/STATIC_LIBRARIES": 7591,
+ "STATIC_LIBRARIES": 11535,
+ "SHARED_LIBRARIES": 10852,
+ "HEADER_LIBRARIES": 1897,
+ "DYLIB_LIBRARIES": 1262,
+ "RLIB_LIBRARIES": 3413,
+ "ROBOLECTRIC": 39,
+ "PACKAGING": 5,
+ "PROC_MACRO_LIBRARIES": 36,
+ "RENDERSCRIPT_BITCODE": 17,
+ "DYLIB_LIBRARIES/RLIB_LIBRARIES": 8,
+ "ETC/FAKE": 1
+
+None of the "SHARED_LIBRARIES/STATIC_LIBRARIES" are double counted in the
+modules with one class
+RLIB/
+
+All of these classes have shared_libs and/or static_libs
+ "EXECUTABLES",
+ "SHARED_LIBRARIES",
+ "STATIC_LIBRARIES",
+ "SHARED_LIBRARIES/STATIC_LIBRARIES", # cc_library
+ "HEADER_LIBRARIES",
+ "NATIVE_TESTS", # test modules
+ "DYLIB_LIBRARIES", # rust
+ "RLIB_LIBRARIES", # rust
+ "ETC", # rust_bindgen
+"""
+
+from collections import defaultdict
+
+import json, os, argparse
+
+ANDROID_PRODUCT_OUT = os.environ.get("ANDROID_PRODUCT_OUT")
+# If a shared library is used less than MAX_SHARED_INCLUSIONS times in a target,
+# then it will likely save memory by changing it to a static library
+# This move will also use less storage
+MAX_SHARED_INCLUSIONS = 2
+# If a static library is used more than MAX_STATIC_INCLUSIONS times in a target,
+# then it will likely save memory by changing it to a shared library
+# This move will also likely use less storage
+MIN_STATIC_INCLUSIONS = 3
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(
+ description=(
+ "Parse module-info.jso and display information about static and"
+ " shared library dependencies."
+ )
+ )
+ parser.add_argument(
+ "--module", dest="module", help="Print the info for the module."
+ )
+ parser.add_argument(
+ "--shared",
+ dest="print_shared",
+ action=argparse.BooleanOptionalAction,
+ help=(
+ "Print the list of libraries that are shared_libs for fewer than {}"
+ " modules.".format(MAX_SHARED_INCLUSIONS)
+ ),
+ )
+ parser.add_argument(
+ "--static",
+ dest="print_static",
+ action=argparse.BooleanOptionalAction,
+ help=(
+ "Print the list of libraries that are static_libs for more than {}"
+ " modules.".format(MIN_STATIC_INCLUSIONS)
+ ),
+ )
+ parser.add_argument(
+ "--recursive",
+ dest="recursive",
+ action=argparse.BooleanOptionalAction,
+ default=True,
+ help=(
+ "Gather all dependencies of EXECUTABLES recursvily before calculating"
+ " the stats. This eliminates duplicates from multiple libraries"
+ " including the same dependencies in a single binary."
+ ),
+ )
+ parser.add_argument(
+ "--both",
+ dest="both",
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help=(
+ "Print a list of libraries that are including libraries as both"
+ " static and shared"
+ ),
+ )
+ return parser.parse_args()
+
+
+class TransitiveHelper:
+
+ def __init__(self):
+ # keep a list of already expanded libraries so we don't end up in a cycle
+ self.visited = defaultdict(lambda: defaultdict(set))
+
+ # module is an object from the module-info dictionary
+ # module_info is the dictionary from module-info.json
+ # modify the module's shared_libs and static_libs with all of the transient
+ # dependencies required from all of the explicit dependencies
+ def flattenDeps(self, module, module_info):
+ libs_snapshot = dict(shared_libs = set(module["shared_libs"]), static_libs = set(module["static_libs"]))
+
+ for lib_class in ["shared_libs", "static_libs"]:
+ for lib in libs_snapshot[lib_class]:
+ if not lib or lib not in module_info:
+ continue
+ if lib in self.visited:
+ module[lib_class].update(self.visited[lib][lib_class])
+ else:
+ res = self.flattenDeps(module_info[lib], module_info)
+ module[lib_class].update(res[lib_class])
+ self.visited[lib][lib_class].update(res[lib_class])
+
+ return module
+
+def main():
+ module_info = json.load(open(ANDROID_PRODUCT_OUT + "/module-info.json"))
+ # turn all of the static_libs and shared_libs lists into sets to make them
+ # easier to update
+ for _, module in module_info.items():
+ module["shared_libs"] = set(module["shared_libs"])
+ module["static_libs"] = set(module["static_libs"])
+
+ args = parse_args()
+
+ if args.module:
+ if args.module not in module_info:
+ print("Module {} does not exist".format(args.module))
+ exit(1)
+
+ includedStatically = defaultdict(set)
+ includedSharedly = defaultdict(set)
+ includedBothly = defaultdict(set)
+ transitive = TransitiveHelper()
+ for name, module in module_info.items():
+ if args.recursive:
+ # in this recursive mode we only want to see what is included by the executables
+ if "EXECUTABLES" not in module["class"]:
+ continue
+ module = transitive.flattenDeps(module, module_info)
+ # filter out fuzzers by their dependency on clang
+ if "libclang_rt.fuzzer" in module["static_libs"]:
+ continue
+ else:
+ if "NATIVE_TESTS" in module["class"]:
+ # We don't care about how tests are including libraries
+ continue
+
+ # count all of the shared and static libs included in this module
+ for lib in module["shared_libs"]:
+ includedSharedly[lib].add(name)
+ for lib in module["static_libs"]:
+ includedStatically[lib].add(name)
+
+ intersection = set(module["shared_libs"]).intersection(
+ module["static_libs"]
+ )
+ if intersection:
+ includedBothly[name] = intersection
+
+ if args.print_shared:
+ print(
+ "Shared libraries that are included by fewer than {} modules on a"
+ " device:".format(MAX_SHARED_INCLUSIONS)
+ )
+ for name, libs in includedSharedly.items():
+ if len(libs) < MAX_SHARED_INCLUSIONS:
+ print("{}: {} included by: {}".format(name, len(libs), libs))
+
+ if args.print_static:
+ print(
+ "Libraries that are included statically by more than {} modules on a"
+ " device:".format(MIN_STATIC_INCLUSIONS)
+ )
+ for name, libs in includedStatically.items():
+ if len(libs) > MIN_STATIC_INCLUSIONS:
+ print("{}: {} included by: {}".format(name, len(libs), libs))
+
+ if args.both:
+ allIncludedBothly = set()
+ for name, libs in includedBothly.items():
+ allIncludedBothly.update(libs)
+
+ print(
+ "List of libraries used both statically and shared in the same"
+ " processes:\n {}\n\n".format("\n".join(sorted(allIncludedBothly)))
+ )
+ print(
+ "List of libraries used both statically and shared in any processes:\n {}".format("\n".join(sorted(includedStatically.keys() & includedSharedly.keys()))))
+
+ if args.module:
+ print(json.dumps(module_info[args.module], default=list, indent=2))
+ print(
+ "{} is included in shared_libs {} times by these modules: {}".format(
+ args.module, len(includedSharedly[args.module]),
+ includedSharedly[args.module]
+ )
+ )
+ print(
+ "{} is included in static_libs {} times by these modules: {}".format(
+ args.module, len(includedStatically[args.module]),
+ includedStatically[args.module]
+ )
+ )
+ print("Shared libs included by this module that are used in fewer than {} processes:\n{}".format(
+ MAX_SHARED_INCLUSIONS, [x for x in module_info[args.module]["shared_libs"] if len(includedSharedly[x]) < MAX_SHARED_INCLUSIONS]))
+
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 8d660f8..465d222 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -68,6 +68,7 @@
from concurrent.futures import ThreadPoolExecutor
from apex_utils import GetApexInfoFromTargetFiles
from common import ZipDelete, PARTITIONS_WITH_CARE_MAP, ExternalError, RunAndCheckOutput, IsSparseImage, MakeTempFile, ZipWrite
+from build_image import FIXED_FILE_TIMESTAMP
if sys.hexversion < 0x02070000:
print("Python 2.7 or newer is required.", file=sys.stderr)
@@ -81,12 +82,6 @@
OPTIONS.replace_updated_files_list = []
OPTIONS.is_signing = False
-# Use a fixed timestamp (01/01/2009 00:00:00 UTC) for files when packaging
-# images. (b/24377993, b/80600931)
-FIXED_FILE_TIMESTAMP = int((
- datetime.datetime(2009, 1, 1, 0, 0, 0, 0, None) -
- datetime.datetime.utcfromtimestamp(0)).total_seconds())
-
def ParseAvbFooter(img_path) -> avbtool.AvbFooter:
with open(img_path, 'rb') as fp:
@@ -594,15 +589,6 @@
if block_list:
image_props["block_list"] = block_list.name
- # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
- # build fingerprint). Also use the legacy build id, because the vbmeta digest
- # isn't available at this point.
- build_info = common.BuildInfo(info_dict, use_legacy_id=True)
- uuid_seed = what + "-" + build_info.GetPartitionFingerprint(what)
- image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
- hash_seed = "hash_seed-" + uuid_seed
- image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
-
build_image.BuildImage(
os.path.join(input_dir, what.upper()), image_props, output_file.name)
@@ -1144,14 +1130,18 @@
item for item in vbmeta_partitions
if item not in vbmeta_vendor.split()]
vbmeta_partitions.append("vbmeta_vendor")
- custom_avb_partitions = OPTIONS.info_dict.get("avb_custom_vbmeta_images_partition_list", "").strip().split()
+ custom_avb_partitions = OPTIONS.info_dict.get(
+ "avb_custom_vbmeta_images_partition_list", "").strip().split()
if custom_avb_partitions:
for avb_part in custom_avb_partitions:
partition_name = "vbmeta_" + avb_part
- included_partitions = OPTIONS.info_dict.get("avb_vbmeta_{}".format(avb_part), "").strip().split()
- assert included_partitions, "Custom vbmeta partition {0} missing avb_vbmeta_{0} prop".format(avb_part)
+ included_partitions = OPTIONS.info_dict.get(
+ "avb_vbmeta_{}".format(avb_part), "").strip().split()
+ assert included_partitions, "Custom vbmeta partition {0} missing avb_vbmeta_{0} prop".format(
+ avb_part)
banner(partition_name)
- logger.info("VBMeta partition {} needs {}".format(partition_name, included_partitions))
+ logger.info("VBMeta partition {} needs {}".format(
+ partition_name, included_partitions))
partitions[partition_name] = AddVBMeta(
output_zip, partitions, partition_name, included_partitions)
vbmeta_partitions = [
@@ -1159,7 +1149,6 @@
if item not in included_partitions]
vbmeta_partitions.append(partition_name)
-
if OPTIONS.info_dict.get("avb_building_vbmeta_image") == "true":
banner("vbmeta")
AddVBMeta(output_zip, partitions, "vbmeta", vbmeta_partitions)
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 9064136..11bd784 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -23,24 +23,34 @@
"""
from __future__ import print_function
+import datetime
import glob
import logging
import os
import os.path
import re
+import shlex
import shutil
import sys
+import uuid
import common
import verity_utils
+
logger = logging.getLogger(__name__)
OPTIONS = common.OPTIONS
BLOCK_SIZE = common.BLOCK_SIZE
BYTES_IN_MB = 1024 * 1024
+# Use a fixed timestamp (01/01/2009 00:00:00 UTC) for files when packaging
+# images. (b/24377993, b/80600931)
+FIXED_FILE_TIMESTAMP = int((
+ datetime.datetime(2009, 1, 1, 0, 0, 0, 0, None) -
+ datetime.datetime.utcfromtimestamp(0)).total_seconds())
+
class BuildImageError(Exception):
"""An Exception raised during image building."""
@@ -487,6 +497,20 @@
raise
+def SetUUIDIfNotExist(image_props):
+
+ # Use repeatable ext4 FS UUID and hash_seed UUID (based on partition name and
+ # build fingerprint). Also use the legacy build id, because the vbmeta digest
+ # isn't available at this point.
+ what = image_props["mount_point"]
+ fingerprint = image_props.get("fingerprint", "")
+ uuid_seed = what + "-" + fingerprint
+ logger.info("Using fingerprint %s for partition %s", fingerprint, what)
+ image_props["uuid"] = str(uuid.uuid5(uuid.NAMESPACE_URL, uuid_seed))
+ hash_seed = "hash_seed-" + uuid_seed
+ image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
+
+
def BuildImage(in_dir, prop_dict, out_file, target_out=None):
"""Builds an image for the files under in_dir and writes it to out_file.
@@ -504,6 +528,7 @@
BuildImageError: On build image failures.
"""
in_dir, fs_config = SetUpInDirAndFsConfig(in_dir, prop_dict)
+ SetUUIDIfNotExist(prop_dict)
build_command = []
fs_type = prop_dict.get("fs_type", "")
@@ -635,6 +660,19 @@
verity_image_builder.Build(out_file)
+def TryParseFingerprint(glob_dict: dict):
+ for (key, val) in glob_dict.items():
+ if not key.endswith("_add_hashtree_footer_args") and not key.endswith("_add_hash_footer_args"):
+ continue
+ for arg in shlex.split(val):
+ m = re.match(r"^com\.android\.build\.\w+\.fingerprint:", arg)
+ if m is None:
+ continue
+ fingerprint = arg[len(m.group()):]
+ glob_dict["fingerprint"] = fingerprint
+ return
+
+
def ImagePropFromGlobalDict(glob_dict, mount_point):
"""Build an image property dictionary from the global dictionary.
@@ -643,7 +681,9 @@
mount_point: such as "system", "data" etc.
"""
d = {}
+ TryParseFingerprint(glob_dict)
+ d["timestamp"] = FIXED_FILE_TIMESTAMP
if "build.prop" in glob_dict:
timestamp = glob_dict["build.prop"].GetProp("ro.build.date.utc")
if timestamp:
@@ -680,6 +720,7 @@
"avb_enable",
"avb_avbtool",
"use_dynamic_partition_size",
+ "fingerprint",
)
for p in common_props:
copy_prop(p, p)
@@ -870,10 +911,9 @@
if item not in vbmeta_vendor.split()]
vbmeta_partitions.append("vbmeta_vendor")
-
partitions = {part: os.path.join(in_dir, part + ".img")
for part in vbmeta_partitions}
- partitions = {part:path for (part, path) in partitions.items() if os.path.exists(path)}
+ partitions = {part: path for (part, path) in partitions.items() if os.path.exists(path)}
common.BuildVBMeta(output_path, partitions, name, vbmeta_partitions)
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 7adc9fa..f92d67c 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -928,20 +928,7 @@
input_file, partition, ramdisk_format=ramdisk_format)
d["build.prop"] = d["system.build.prop"]
- # Set up the salt (based on fingerprint) that will be used when adding AVB
- # hash / hashtree footers.
if d.get("avb_enable") == "true":
- build_info = BuildInfo(d, use_legacy_id=True)
- for partition in PARTITIONS_WITH_BUILD_PROP:
- fingerprint = build_info.GetPartitionFingerprint(partition)
- if fingerprint:
- d["avb_{}_salt".format(partition)] = sha256(
- fingerprint.encode()).hexdigest()
-
- # Set up the salt for partitions without build.prop
- if build_info.fingerprint:
- d["avb_salt"] = sha256(build_info.fingerprint.encode()).hexdigest()
-
# Set the vbmeta digest if exists
try:
d["vbmeta_digest"] = read_helper("META/vbmeta_digest.txt").rstrip()
@@ -2137,20 +2124,19 @@
archvie. Non-matching patterns will be filtered out. If there's no match
after the filtering, no file will be unzipped.
"""
- cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
- if patterns is not None:
+ with zipfile.ZipFile(filename, allowZip64=True, mode="r") as input_zip:
# Filter out non-matching patterns. unzip will complain otherwise.
- with zipfile.ZipFile(filename, allowZip64=True) as input_zip:
+ if patterns is not None:
names = input_zip.namelist()
- filtered = [
- pattern for pattern in patterns if fnmatch.filter(names, pattern)]
+ filtered = [name for name in names if any(
+ [fnmatch.fnmatch(name, p) for p in patterns])]
- # There isn't any matching files. Don't unzip anything.
- if not filtered:
- return
- cmd.extend(filtered)
-
- RunAndCheckOutput(cmd)
+ # There isn't any matching files. Don't unzip anything.
+ if not filtered:
+ return
+ input_zip.extractall(dirname, filtered)
+ else:
+ input_zip.extractall(dirname)
def UnzipTemp(filename, patterns=None):
diff --git a/tools/releasetools/verity_utils.py b/tools/releasetools/verity_utils.py
index dddb7f4..7caeed4 100644
--- a/tools/releasetools/verity_utils.py
+++ b/tools/releasetools/verity_utils.py
@@ -31,6 +31,7 @@
import common
import sparse_img
from rangelib import RangeSet
+from hashlib import sha256
logger = logging.getLogger(__name__)
@@ -42,6 +43,7 @@
MAX_VBMETA_SIZE = 64 * 1024
MAX_FOOTER_SIZE = 4096
+
class BuildVerityImageError(Exception):
"""An Exception raised during verity image building."""
@@ -64,6 +66,11 @@
# partition_size could be None at this point, if using dynamic partitions.
if partition_size:
partition_size = int(partition_size)
+ # Set up the salt (based on fingerprint) that will be used when adding AVB
+ # hash / hashtree footers.
+ salt = prop_dict.get("avb_salt")
+ if salt is None:
+ salt = sha256(prop_dict.get("fingerprint", "").encode()).hexdigest()
# Verified Boot 2.0
if (prop_dict.get("avb_hash_enable") == "true" or
@@ -81,7 +88,7 @@
prop_dict["avb_avbtool"],
key_path,
algorithm,
- prop_dict.get("avb_salt"),
+ salt,
prop_dict["avb_add_hash_footer_args"])
# Image uses hashtree footer.
@@ -92,7 +99,7 @@
prop_dict["avb_avbtool"],
key_path,
algorithm,
- prop_dict.get("avb_salt"),
+ salt,
prop_dict["avb_add_hashtree_footer_args"])
return None
@@ -279,7 +286,7 @@
def CreateCustomImageBuilder(info_dict, partition_name, partition_size,
- key_path, algorithm, signing_args):
+ key_path, algorithm, signing_args):
builder = None
if info_dict.get("avb_enable") == "true":
builder = VerifiedBootVersion2VerityImageBuilder(