Merge "Build the general tests host shared libs." into main
diff --git a/core/android_soong_config_vars.mk b/core/android_soong_config_vars.mk
index 90ac75f..9f43a3e 100644
--- a/core/android_soong_config_vars.mk
+++ b/core/android_soong_config_vars.mk
@@ -199,5 +199,12 @@
# Add crashrecovery build flag to soong
$(call soong_config_set,ANDROID,release_crashrecovery_module,$(RELEASE_CRASHRECOVERY_MODULE))
+ifeq (true,$(RELEASE_CRASHRECOVERY_FILE_MOVE))
+ $(call soong_config_set,ANDROID,crashrecovery_files_in_module,true)
+ $(call soong_config_set,ANDROID,crashrecovery_files_in_platform,false)
+else
+ $(call soong_config_set,ANDROID,crashrecovery_files_in_module,false)
+ $(call soong_config_set,ANDROID,crashrecovery_files_in_platform,true)
+endif
# Weirdly required because platform_bootclasspath is using AUTO namespace
$(call soong_config_set,AUTO,release_crashrecovery_module,$(RELEASE_CRASHRECOVERY_MODULE))
diff --git a/core/version_util.mk b/core/version_util.mk
index 0ed4499..6cda0fc 100644
--- a/core/version_util.mk
+++ b/core/version_util.mk
@@ -31,6 +31,7 @@
# PLATFORM_VNDK_VERSION
# PLATFORM_SYSTEMSDK_VERSIONS
# PLATFORM_VERSION_LAST_STABLE
+# PLATFORM_VERSION_KNOWN_CODENAMES
#
# Look for an optional file containing overrides of the defaults,
@@ -95,17 +96,10 @@
PLATFORM_VERSION_LAST_STABLE := $(RELEASE_PLATFORM_VERSION_LAST_STABLE)
.KATI_READONLY := PLATFORM_VERSION_LAST_STABLE
-
-# This are all known codenames. Should this move into the release config?
-PLATFORM_VERSION_KNOWN_CODENAMES := \
-Base Base11 Cupcake Donut Eclair Eclair01 EclairMr1 Froyo Gingerbread GingerbreadMr1 \
-Honeycomb HoneycombMr1 HoneycombMr2 IceCreamSandwich IceCreamSandwichMr1 \
-JellyBean JellyBeanMr1 JellyBeanMr2 Kitkat KitkatWatch Lollipop LollipopMr1 M N NMr1 O OMr1 P \
-Q R S Sv2 Tiramisu UpsideDownCake VanillaIceCream
-
-# Convert from space separated list to comma separated
-PLATFORM_VERSION_KNOWN_CODENAMES := \
- $(call normalize-comma-list,$(PLATFORM_VERSION_KNOWN_CODENAMES))
+ifdef PLATFORM_VERSION_KNOWN_CODENAMES
+ $(error Do not set PLATFORM_VERSION_KNOWN_CODENAMES directly. Use RELEASE_PLATFORM_VERSION_KNOWN_CODENAMES. value: $(PLATFORM_VERSION_KNOWN_CODENAMES))
+endif
+PLATFORM_VERSION_KNOWN_CODENAMES := $(RELEASE_PLATFORM_VERSION_KNOWN_CODENAMES)
.KATI_READONLY := PLATFORM_VERSION_KNOWN_CODENAMES
ifndef PLATFORM_VERSION
diff --git a/target/product/base_system.mk b/target/product/base_system.mk
index 277223e..7d0222d 100644
--- a/target/product/base_system.mk
+++ b/target/product/base_system.mk
@@ -18,6 +18,7 @@
PRODUCT_PACKAGES += \
abx \
adbd_system_api \
+ aflags \
am \
android.hidl.base-V1.0-java \
android.hidl.manager-V1.0-java \
diff --git a/target/product/default_art_config.mk b/target/product/default_art_config.mk
index 3e3918c..dca9baa 100644
--- a/target/product/default_art_config.mk
+++ b/target/product/default_art_config.mk
@@ -74,6 +74,7 @@
com.android.media:updatable-media \
com.android.mediaprovider:framework-mediaprovider \
com.android.mediaprovider:framework-pdf \
+ com.android.mediaprovider:framework-pdf-v \
com.android.ondevicepersonalization:framework-ondevicepersonalization \
com.android.os.statsd:framework-statsd \
com.android.permission:framework-permission \
@@ -108,6 +109,7 @@
# Keep the list sorted by module names and then library names.
PRODUCT_APEX_BOOT_JARS_FOR_SOURCE_BUILD_ONLY := \
com.android.mediaprovider:framework-pdf \
+ com.android.mediaprovider:framework-pdf-v \
# List of system_server classpath jars delivered via apex.
# Keep the list sorted by module names and then library names.
diff --git a/tools/aconfig/Cargo.toml b/tools/aconfig/Cargo.toml
index 970fdcf..95f1215 100644
--- a/tools/aconfig/Cargo.toml
+++ b/tools/aconfig/Cargo.toml
@@ -4,6 +4,7 @@
"aconfig",
"aconfig_protos",
"aconfig_storage_file",
+ "aflags",
"printflags"
]
diff --git a/tools/aconfig/TEST_MAPPING b/tools/aconfig/TEST_MAPPING
index 1a3f79a..e42b5d3 100644
--- a/tools/aconfig/TEST_MAPPING
+++ b/tools/aconfig/TEST_MAPPING
@@ -74,6 +74,11 @@
{
// aconfig_storage read api cpp integration tests
"name": "aconfig_storage.test.cpp"
+ },
+ {
+ // aflags CLI unit tests
+ // TODO(b/326062088): add to presubmit once proven in postsubmit.
+ "name": "aflags.test"
}
]
}
diff --git a/tools/aconfig/aflags/Android.bp b/tools/aconfig/aflags/Android.bp
new file mode 100644
index 0000000..c65da97
--- /dev/null
+++ b/tools/aconfig/aflags/Android.bp
@@ -0,0 +1,29 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+ name: "aflags.defaults",
+ edition: "2021",
+ clippy_lints: "android",
+ lints: "android",
+ srcs: ["src/main.rs"],
+ rustlibs: [
+ "libaconfig_protos",
+ "libanyhow",
+ "libclap",
+ "libprotobuf",
+ "libregex",
+ ],
+}
+
+rust_binary {
+ name: "aflags",
+ defaults: ["aflags.defaults"],
+}
+
+rust_test_host {
+ name: "aflags.test",
+ defaults: ["aflags.defaults"],
+ test_suites: ["general-tests"],
+}
diff --git a/tools/aconfig/aflags/Cargo.toml b/tools/aconfig/aflags/Cargo.toml
new file mode 100644
index 0000000..3350a6cd
--- /dev/null
+++ b/tools/aconfig/aflags/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "aflags"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1.0.69"
+paste = "1.0.11"
+clap = { version = "4", features = ["derive"] }
+protobuf = "3.2.0"
+regex = "1.10.3"
+aconfig_protos = { path = "../aconfig_protos" }
diff --git a/tools/aconfig/aflags/src/device_config_source.rs b/tools/aconfig/aflags/src/device_config_source.rs
new file mode 100644
index 0000000..12a62cf
--- /dev/null
+++ b/tools/aconfig/aflags/src/device_config_source.rs
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+use crate::{Flag, FlagPermission, FlagSource, ValuePickedFrom};
+use aconfig_protos::ProtoFlagPermission as ProtoPermission;
+use aconfig_protos::ProtoFlagState as ProtoState;
+use aconfig_protos::ProtoParsedFlag;
+use aconfig_protos::ProtoParsedFlags;
+use anyhow::{anyhow, bail, Result};
+use regex::Regex;
+use std::collections::BTreeMap;
+use std::collections::HashMap;
+use std::process::Command;
+use std::{fs, str};
+
+pub struct DeviceConfigSource {}
+
+fn convert_parsed_flag(flag: &ProtoParsedFlag) -> Flag {
+ let namespace = flag.namespace().to_string();
+ let package = flag.package().to_string();
+ let name = flag.name().to_string();
+
+ let container = if flag.container().is_empty() {
+ "system".to_string()
+ } else {
+ flag.container().to_string()
+ };
+
+ let value = match flag.state() {
+ ProtoState::ENABLED => "true",
+ ProtoState::DISABLED => "false",
+ }
+ .to_string();
+
+ let permission = match flag.permission() {
+ ProtoPermission::READ_ONLY => FlagPermission::ReadOnly,
+ ProtoPermission::READ_WRITE => FlagPermission::ReadWrite,
+ };
+
+ Flag {
+ namespace,
+ package,
+ name,
+ container,
+ value,
+ permission,
+ value_picked_from: ValuePickedFrom::Default,
+ }
+}
+
+fn read_pb_files() -> Result<Vec<Flag>> {
+ let mut flags: BTreeMap<String, Flag> = BTreeMap::new();
+ for partition in ["system", "system_ext", "product", "vendor"] {
+ let path = format!("/{}/etc/aconfig_flags.pb", partition);
+ let Ok(bytes) = fs::read(&path) else {
+ eprintln!("warning: failed to read {}", path);
+ continue;
+ };
+ let parsed_flags: ProtoParsedFlags = protobuf::Message::parse_from_bytes(&bytes)?;
+ for flag in parsed_flags.parsed_flag {
+ let key = format!("{}.{}", flag.package(), flag.name());
+ let container = if flag.container().is_empty() {
+ "system".to_string()
+ } else {
+ flag.container().to_string()
+ };
+
+ if container.eq(partition) {
+ flags.insert(key, convert_parsed_flag(&flag));
+ }
+ }
+ }
+ Ok(flags.values().cloned().collect())
+}
+
+fn parse_device_config(raw: &str) -> Result<HashMap<String, String>> {
+ let mut flags = HashMap::new();
+ let regex = Regex::new(r"(?m)^([[[:alnum:]]_]+/[[[:alnum:]]_\.]+)=(true|false)$")?;
+ for capture in regex.captures_iter(raw) {
+ let key =
+ capture.get(1).ok_or(anyhow!("invalid device_config output"))?.as_str().to_string();
+ let value = capture.get(2).ok_or(anyhow!("invalid device_config output"))?.as_str();
+ flags.insert(key, value.to_string());
+ }
+ Ok(flags)
+}
+
+fn read_device_config_output(command: &str) -> Result<String> {
+ let output = Command::new("/system/bin/device_config").arg(command).output()?;
+ if !output.status.success() {
+ let reason = match output.status.code() {
+ Some(code) => format!("exit code {}", code),
+ None => "terminated by signal".to_string(),
+ };
+ bail!("failed to execute device_config: {}", reason);
+ }
+ Ok(str::from_utf8(&output.stdout)?.to_string())
+}
+
+fn read_device_config_flags() -> Result<HashMap<String, String>> {
+ let list_output = read_device_config_output("list")?;
+ parse_device_config(&list_output)
+}
+
+fn reconcile(pb_flags: &[Flag], dc_flags: HashMap<String, String>) -> Vec<Flag> {
+ pb_flags
+ .iter()
+ .map(|f| {
+ dc_flags
+ .get(&format!("{}/{}.{}", f.namespace, f.package, f.name))
+ .map(|value| {
+ if value.eq(&f.value) {
+ Flag { value_picked_from: ValuePickedFrom::Default, ..f.clone() }
+ } else {
+ Flag {
+ value_picked_from: ValuePickedFrom::Server,
+ value: value.to_string(),
+ ..f.clone()
+ }
+ }
+ })
+ .unwrap_or(f.clone())
+ })
+ .collect()
+}
+
+impl FlagSource for DeviceConfigSource {
+ fn list_flags() -> Result<Vec<Flag>> {
+ let pb_flags = read_pb_files()?;
+ let dc_flags = read_device_config_flags()?;
+
+ let flags = reconcile(&pb_flags, dc_flags);
+ Ok(flags)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_parse_device_config() {
+ let input = r#"
+namespace_one/com.foo.bar.flag_one=true
+namespace_one/com.foo.bar.flag_two=false
+random_noise;
+namespace_two/android.flag_one=true
+namespace_two/android.flag_two=nonsense
+"#;
+ let expected = HashMap::from([
+ ("namespace_one/com.foo.bar.flag_one".to_string(), "true".to_string()),
+ ("namespace_one/com.foo.bar.flag_two".to_string(), "false".to_string()),
+ ("namespace_two/android.flag_one".to_string(), "true".to_string()),
+ ]);
+ let actual = parse_device_config(input).unwrap();
+ assert_eq!(expected, actual);
+ }
+}
diff --git a/tools/aconfig/aflags/src/main.rs b/tools/aconfig/aflags/src/main.rs
new file mode 100644
index 0000000..1e2a7a0
--- /dev/null
+++ b/tools/aconfig/aflags/src/main.rs
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+//! `aflags` is a device binary to read and write aconfig flags.
+
+use anyhow::Result;
+use clap::Parser;
+
+mod device_config_source;
+use device_config_source::DeviceConfigSource;
+
+#[derive(Clone)]
+enum FlagPermission {
+ ReadOnly,
+ ReadWrite,
+}
+
+impl ToString for FlagPermission {
+ fn to_string(&self) -> String {
+ match &self {
+ Self::ReadOnly => "read-only".into(),
+ Self::ReadWrite => "read-write".into(),
+ }
+ }
+}
+
+#[derive(Clone)]
+enum ValuePickedFrom {
+ Default,
+ Server,
+}
+
+impl ToString for ValuePickedFrom {
+ fn to_string(&self) -> String {
+ match &self {
+ Self::Default => "default".into(),
+ Self::Server => "server".into(),
+ }
+ }
+}
+
+#[derive(Clone)]
+struct Flag {
+ namespace: String,
+ name: String,
+ package: String,
+ container: String,
+ value: String,
+ permission: FlagPermission,
+ value_picked_from: ValuePickedFrom,
+}
+
+trait FlagSource {
+ fn list_flags() -> Result<Vec<Flag>>;
+}
+
+const ABOUT_TEXT: &str = "Tool for reading and writing flags.
+
+Rows in the table from the `list` command follow this format:
+
+ package flag_name value provenance permission container
+
+ * `package`: package set for this flag in its .aconfig definition.
+ * `flag_name`: flag name, also set in definition.
+ * `value`: the value read from the flag.
+ * `provenance`: one of:
+ + `default`: the flag value comes from its build-time default.
+ + `server`: the flag value comes from a server override.
+ * `permission`: read-write or read-only.
+ * `container`: the container for the flag, configured in its definition.
+";
+
+#[derive(Parser, Debug)]
+#[clap(long_about=ABOUT_TEXT)]
+struct Cli {
+ #[clap(subcommand)]
+ command: Command,
+}
+
+#[derive(Parser, Debug)]
+enum Command {
+ /// List all aconfig flags on this device.
+ List,
+}
+
+struct PaddingInfo {
+ longest_package_col: usize,
+ longest_name_col: usize,
+ longest_val_col: usize,
+ longest_value_picked_from_col: usize,
+ longest_permission_col: usize,
+}
+
+fn format_flag_row(flag: &Flag, info: &PaddingInfo) -> String {
+ let pkg = &flag.package;
+ let p0 = info.longest_package_col + 1;
+
+ let name = &flag.name;
+ let p1 = info.longest_name_col + 1;
+
+ let val = flag.value.to_string();
+ let p2 = info.longest_val_col + 1;
+
+ let value_picked_from = flag.value_picked_from.to_string();
+ let p3 = info.longest_value_picked_from_col + 1;
+
+ let perm = flag.permission.to_string();
+ let p4 = info.longest_permission_col + 1;
+
+ let container = &flag.container;
+
+ format!("{pkg:p0$}{name:p1$}{val:p2$}{value_picked_from:p3$}{perm:p4$}{container}\n")
+}
+
+fn list() -> Result<String> {
+ let flags = DeviceConfigSource::list_flags()?;
+ let padding_info = PaddingInfo {
+ longest_package_col: flags.iter().map(|f| f.package.len()).max().unwrap_or(0),
+ longest_name_col: flags.iter().map(|f| f.name.len()).max().unwrap_or(0),
+ longest_val_col: flags.iter().map(|f| f.value.to_string().len()).max().unwrap_or(0),
+ longest_value_picked_from_col: flags
+ .iter()
+ .map(|f| f.value_picked_from.to_string().len())
+ .max()
+ .unwrap_or(0),
+ longest_permission_col: flags
+ .iter()
+ .map(|f| f.permission.to_string().len())
+ .max()
+ .unwrap_or(0),
+ };
+
+ let mut result = String::from("");
+ for flag in flags {
+ let row = format_flag_row(&flag, &padding_info);
+ result.push_str(&row);
+ }
+ Ok(result)
+}
+
+fn main() {
+ let cli = Cli::parse();
+ let output = match cli.command {
+ Command::List => list(),
+ };
+ match output {
+ Ok(text) => println!("{text}"),
+ Err(msg) => println!("Error: {}", msg),
+ }
+}
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index e521e1f..dbbbca2 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -261,7 +261,7 @@
Specify the VABC cow version to be used
--compression_factor
- Specify the maximum block size to be compressed at once during OTA. supported options: 4k, 8k, 16k, 32k, 64k, 128k
+ Specify the maximum block size to be compressed at once during OTA. supported options: 4k, 8k, 16k, 32k, 64k, 128k, 256k
"""
from __future__ import print_function
@@ -603,7 +603,7 @@
This function modifies ab_partitions list with the desired partitions before
calling the brillo_update_payload script. It also cleans up the reference to
- the excluded partitions in the info file, e.g misc_info.txt.
+ the excluded partitions in the info file, e.g. misc_info.txt.
Args:
input_file: The input target-files.zip filename.
@@ -1276,11 +1276,11 @@
raise ValueError("Cannot parse value %r for option %r - only "
"integers are allowed." % (a, o))
elif o in ("--compression_factor"):
- values = ["4k", "8k", "16k", "32k", "64k", "128k"]
+ values = ["4k", "8k", "16k", "32k", "64k", "128k", "256k"]
if a[:-1].isdigit() and a in values and a.endswith("k"):
OPTIONS.compression_factor = str(int(a[:-1]) * 1024)
else:
- raise ValueError("Please specify value from following options: 4k, 8k, 16k, 32k, 64k, 128k")
+ raise ValueError("Please specify value from following options: 4k, 8k, 16k, 32k, 64k, 128k", "256k")
elif o == "--vabc_cow_version":
if a.isdigit():