diff options
| -rw-r--r-- | Android.bp | 25 | ||||
| -rw-r--r-- | android/Android.bp | 1 | ||||
| -rw-r--r-- | android/build_prop.go | 41 | ||||
| -rw-r--r-- | android/buildinfo_prop.go | 132 | ||||
| -rw-r--r-- | android/config.go | 4 | ||||
| -rw-r--r-- | android/variable.go | 2 | ||||
| -rw-r--r-- | scripts/Android.bp | 6 | ||||
| -rwxr-xr-x | scripts/buildinfo.py | 191 | ||||
| -rw-r--r-- | scripts/gen_build_prop.py | 17 |
9 files changed, 351 insertions, 68 deletions
diff --git a/Android.bp b/Android.bp index c37d777db..0d1ff02c7 100644 --- a/Android.bp +++ b/Android.bp @@ -121,6 +121,20 @@ dexpreopt_systemserver_check { name: "dexpreopt_systemserver_check", } +// buildinfo.prop contains common properties for system/build.prop, like ro.build.version.* +// TODO(b/322090587): merge this to gen_build_prop.py script. +buildinfo_prop { + name: "buildinfo.prop", + + // not installable because this will be included to system/build.prop + installable: false, + + product_config: ":product_config", + + // Currently, only microdroid can refer to buildinfo.prop + visibility: ["//packages/modules/Virtualization/build/microdroid"], +} + // container for apex_contributions selected using build flags all_apex_contributions { name: "all_apex_contributions", @@ -130,14 +144,3 @@ product_config { name: "product_config", visibility: ["//device/google/cuttlefish/system_image"], } - -build_prop { - name: "system-build.prop", - stem: "build.prop", - product_config: ":product_config", - // Currently, only microdroid and cf system image can refer to system-build.prop - visibility: [ - "//device/google/cuttlefish/system_image", - "//packages/modules/Virtualization/build/microdroid", - ], -} diff --git a/android/Android.bp b/android/Android.bp index ee190216b..774d24a20 100644 --- a/android/Android.bp +++ b/android/Android.bp @@ -39,6 +39,7 @@ bootstrap_go_package { "arch_module_context.go", "base_module_context.go", "build_prop.go", + "buildinfo_prop.go", "compliance_metadata.go", "config.go", "container.go", diff --git a/android/build_prop.go b/android/build_prop.go index c226431a7..45c17c35b 100644 --- a/android/build_prop.go +++ b/android/build_prop.go @@ -31,6 +31,10 @@ type buildPropProperties struct { // properties in prop_files. Block_list []string + // Path to the input prop files. The contents of the files are directly + // emitted to the output + Prop_files []string `android:"path"` + // Files to be appended at the end of build.prop. These files are appended after // post_process_props without any further checking. Footer_files []string `android:"path"` @@ -52,29 +56,6 @@ func (p *buildPropModule) stem() string { return proptools.StringDefault(p.properties.Stem, "build.prop") } -func (p *buildPropModule) propFiles(ctx ModuleContext) Paths { - partition := p.PartitionTag(ctx.DeviceConfig()) - if partition == "system" { - return ctx.Config().SystemPropFiles(ctx) - } - return nil -} - -func shouldAddBuildThumbprint(config Config) bool { - knownOemProperties := []string{ - "ro.product.brand", - "ro.product.name", - "ro.product.device", - } - - for _, knownProp := range knownOemProperties { - if InList(knownProp, config.OemProperties()) { - return true - } - } - return false -} - func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { p.outputFilePath = PathForModuleOut(ctx, "build.prop").OutputPath if !ctx.Config().KatiEnabled() { @@ -112,7 +93,6 @@ func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx)) cmd.FlagWithInput("--product-config=", PathForModuleSrc(ctx, proptools.String(p.properties.Product_config))) cmd.FlagWithArg("--partition=", partition) - cmd.FlagForEachInput("--prop-files=", ctx.Config().SystemPropFiles(ctx)) cmd.FlagWithOutput("--out=", p.outputFilePath) postProcessCmd := rule.Command().BuiltTool("post_process_props") @@ -134,19 +114,6 @@ func (p *buildPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { ctx.SetOutputFiles(Paths{p.outputFilePath}, "") } -func (p *buildPropModule) AndroidMkEntries() []AndroidMkEntries { - return []AndroidMkEntries{{ - Class: "ETC", - OutputFile: OptionalPathForPath(p.outputFilePath), - ExtraEntries: []AndroidMkExtraEntriesFunc{ - func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) { - entries.SetString("LOCAL_MODULE_PATH", p.installPath.String()) - entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base()) - }, - }, - }} -} - // build_prop module generates {partition}/build.prop file. At first common build properties are // printed based on Soong config variables. And then prop_files are printed as-is. Finally, // post_process_props tool is run to check if the result build.prop is valid or not. diff --git a/android/buildinfo_prop.go b/android/buildinfo_prop.go new file mode 100644 index 000000000..bba4c0d24 --- /dev/null +++ b/android/buildinfo_prop.go @@ -0,0 +1,132 @@ +// Copyright 2022 Google Inc. All rights reserved. +// +// 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. + +package android + +import ( + "github.com/google/blueprint/proptools" +) + +func init() { + ctx := InitRegistrationContext + ctx.RegisterModuleType("buildinfo_prop", buildinfoPropFactory) +} + +type buildinfoPropProperties struct { + // Whether this module is directly installable to one of the partitions. Default: true. + Installable *bool + + Product_config *string `android:"path"` +} + +type buildinfoPropModule struct { + ModuleBase + + properties buildinfoPropProperties + + outputFilePath OutputPath + installPath InstallPath +} + +func (p *buildinfoPropModule) installable() bool { + return proptools.BoolDefault(p.properties.Installable, true) +} + +func shouldAddBuildThumbprint(config Config) bool { + knownOemProperties := []string{ + "ro.product.brand", + "ro.product.name", + "ro.product.device", + } + + for _, knownProp := range knownOemProperties { + if InList(knownProp, config.OemProperties()) { + return true + } + } + return false +} + +func (p *buildinfoPropModule) GenerateAndroidBuildActions(ctx ModuleContext) { + if ctx.ModuleName() != "buildinfo.prop" || ctx.ModuleDir() != "build/soong" { + ctx.ModuleErrorf("There can only be one buildinfo_prop module in build/soong") + return + } + p.outputFilePath = PathForModuleOut(ctx, p.Name()).OutputPath + ctx.SetOutputFiles(Paths{p.outputFilePath}, "") + + if !ctx.Config().KatiEnabled() { + WriteFileRule(ctx, p.outputFilePath, "# no buildinfo.prop if kati is disabled") + return + } + + rule := NewRuleBuilder(pctx, ctx) + + config := ctx.Config() + + cmd := rule.Command().BuiltTool("buildinfo") + + cmd.FlagWithInput("--build-hostname-file=", config.BuildHostnameFile(ctx)) + // Note: depending on BuildNumberFile will cause the build.prop file to be rebuilt + // every build, but that's intentional. + cmd.FlagWithInput("--build-number-file=", config.BuildNumberFile(ctx)) + // Export build thumbprint only if the product has specified at least one oem fingerprint property + // b/17888863 + if shouldAddBuildThumbprint(config) { + // In the previous make implementation, a dependency was not added on the thumbprint file + cmd.FlagWithArg("--build-thumbprint-file=", config.BuildThumbprintFile(ctx).String()) + } + cmd.FlagWithArg("--build-username=", config.Getenv("BUILD_USERNAME")) + // Technically we should also have a dependency on BUILD_DATETIME_FILE, + // but it can be either an absolute or relative path, which is hard to turn into + // a Path object. So just rely on the BuildNumberFile always changing to cause + // us to rebuild. + cmd.FlagWithArg("--date-file=", ctx.Config().Getenv("BUILD_DATETIME_FILE")) + cmd.FlagWithInput("--platform-preview-sdk-fingerprint-file=", ApiFingerprintPath(ctx)) + cmd.FlagWithInput("--product-config=", PathForModuleSrc(ctx, proptools.String(p.properties.Product_config))) + cmd.FlagWithOutput("--out=", p.outputFilePath) + + rule.Build(ctx.ModuleName(), "generating buildinfo props") + + if !p.installable() { + p.SkipInstall() + } + + p.installPath = PathForModuleInstall(ctx) + ctx.InstallFile(p.installPath, p.Name(), p.outputFilePath) +} + +func (p *buildinfoPropModule) AndroidMkEntries() []AndroidMkEntries { + return []AndroidMkEntries{{ + Class: "ETC", + OutputFile: OptionalPathForPath(p.outputFilePath), + ExtraEntries: []AndroidMkExtraEntriesFunc{ + func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) { + entries.SetString("LOCAL_MODULE_PATH", p.installPath.String()) + entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base()) + entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable()) + }, + }, + }} +} + +// buildinfo_prop module generates a build.prop file, which contains a set of common +// system/build.prop properties, such as ro.build.version.*. Not all properties are implemented; +// currently this module is only for microdroid. +func buildinfoPropFactory() Module { + module := &buildinfoPropModule{} + module.AddProperties(&module.properties) + InitAndroidModule(module) + return module +} diff --git a/android/config.go b/android/config.go index 92aae7e16..eff9fdd5b 100644 --- a/android/config.go +++ b/android/config.go @@ -2077,7 +2077,3 @@ func (c *config) UseDebugArt() bool { return Bool(c.productVariables.Eng) } - -func (c *config) SystemPropFiles(ctx PathContext) Paths { - return PathsForSource(ctx, c.productVariables.SystemPropFiles) -} diff --git a/android/variable.go b/android/variable.go index 5356e8525..eb0e210c5 100644 --- a/android/variable.go +++ b/android/variable.go @@ -506,8 +506,6 @@ type ProductVariables struct { OemProperties []string `json:",omitempty"` ArtTargetIncludeDebugBuild *bool `json:",omitempty"` - - SystemPropFiles []string `json:",omitempty"` } type PartitionQualifiedVariablesType struct { diff --git a/scripts/Android.bp b/scripts/Android.bp index 3d81b83c2..91aa19560 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -306,6 +306,12 @@ python_binary_host { } python_binary_host { + name: "buildinfo", + main: "buildinfo.py", + srcs: ["buildinfo.py"], +} + +python_binary_host { name: "extra_install_zips_file_list", main: "extra_install_zips_file_list.py", srcs: ["extra_install_zips_file_list.py"], diff --git a/scripts/buildinfo.py b/scripts/buildinfo.py new file mode 100755 index 000000000..8a24b63a8 --- /dev/null +++ b/scripts/buildinfo.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +# +# 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. +# +"""A tool for generating buildinfo.prop""" + +import argparse +import contextlib +import json +import os +import subprocess + +TEST_KEY_DIR = "build/make/target/product/security" + +def get_build_variant(product_config): + if product_config["Eng"]: + return "eng" + elif product_config["Debuggable"]: + return "userdebug" + else: + return "user" + +def get_build_flavor(product_config): + build_flavor = product_config["DeviceProduct"] + "-" + get_build_variant(product_config) + if "address" in product_config.get("SanitizeDevice", []) and "_asan" not in build_flavor: + build_flavor += "_asan" + return build_flavor + +def get_build_keys(product_config): + default_cert = product_config.get("DefaultAppCertificate", "") + if default_cert == "" or default_cert == os.path.join(TEST_KEY_DIR, "testKey"): + return "test-keys" + return "dev-keys" + +def parse_args(): + """Parse commandline arguments.""" + parser = argparse.ArgumentParser() + parser.add_argument('--build-hostname-file', required=True, type=argparse.FileType('r')), + parser.add_argument('--build-number-file', required=True, type=argparse.FileType('r')) + parser.add_argument('--build-thumbprint-file', type=argparse.FileType('r')) + parser.add_argument('--build-username', required=True) + parser.add_argument('--date-file', required=True, type=argparse.FileType('r')) + parser.add_argument('--platform-preview-sdk-fingerprint-file', + required=True, + type=argparse.FileType('r')) + parser.add_argument('--product-config', required=True, type=argparse.FileType('r')) + parser.add_argument('--out', required=True, type=argparse.FileType('w')) + + option = parser.parse_args() + + product_config = json.load(option.product_config) + build_flags = product_config["BuildFlags"] + + option.build_flavor = get_build_flavor(product_config) + option.build_keys = get_build_keys(product_config) + option.build_id = product_config["BuildId"] + option.build_type = product_config["BuildType"] + option.build_variant = get_build_variant(product_config) + option.build_version_tags = product_config["BuildVersionTags"] + option.cpu_abis = product_config["DeviceAbi"] + option.default_locale = None + if len(product_config.get("ProductLocales", [])) > 0: + option.default_locale = product_config["ProductLocales"][0] + option.default_wifi_channels = product_config.get("ProductDefaultWifiChannels", []) + option.device = product_config["DeviceName"] + option.display_build_number = product_config["DisplayBuildNumber"] + option.platform_base_os = product_config["Platform_base_os"] + option.platform_display_version = product_config["Platform_display_version_name"] + option.platform_min_supported_target_sdk_version = build_flags["RELEASE_PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION"] + option.platform_preview_sdk_version = product_config["Platform_preview_sdk_version"] + option.platform_sdk_version = product_config["Platform_sdk_version"] + option.platform_security_patch = product_config["Platform_security_patch"] + option.platform_version = product_config["Platform_version_name"] + option.platform_version_codename = product_config["Platform_sdk_codename"] + option.platform_version_all_codenames = product_config["Platform_version_active_codenames"] + option.platform_version_known_codenames = product_config["Platform_version_known_codenames"] + option.platform_version_last_stable = product_config["Platform_version_last_stable"] + option.product = product_config["DeviceProduct"] + option.use_vbmeta_digest_in_fingerprint = product_config["BoardUseVbmetaDigestInFingerprint"] + + return option + +def main(): + option = parse_args() + + build_hostname = option.build_hostname_file.read().strip() + build_number = option.build_number_file.read().strip() + build_version_tags_list = option.build_version_tags + if option.build_type == "debug": + build_version_tags_list.append("debug") + build_version_tags_list.append(option.build_keys) + build_version_tags = ",".join(sorted(set(build_version_tags_list))) + + raw_date = option.date_file.read().strip() + date = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip() + date_utc = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip() + + # build_desc is human readable strings that describe this build. This has the same info as the + # build fingerprint. + # e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys" + build_desc = f"{option.product}-{option.build_variant} {option.platform_version} " \ + f"{option.build_id} {build_number} {build_version_tags}" + + platform_preview_sdk_fingerprint = option.platform_preview_sdk_fingerprint_file.read().strip() + + with contextlib.redirect_stdout(option.out): + print("# begin build properties") + print("# autogenerated by buildinfo.py") + + # The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest. + if option.use_vbmeta_digest_in_fingerprint: + print(f"ro.build.legacy.id={option.build_id}") + else: + print(f"ro.build.id?={option.build_id}") + + # ro.build.display.id is shown under Settings -> About Phone + if option.build_variant == "user": + # User builds should show: + # release build number or branch.buld_number non-release builds + + # Dev. branches should have DISPLAY_BUILD_NUMBER set + if option.display_build_number: + print(f"ro.build.display.id?={option.build_id}.{build_number} {option.build_keys}") + else: + print(f"ro.build.display.id?={option.build_id} {option.build_keys}") + else: + # Non-user builds should show detailed build information (See build desc above) + print(f"ro.build.display.id?={build_desc}") + print(f"ro.build.version.incremental={build_number}") + print(f"ro.build.version.sdk={option.platform_sdk_version}") + print(f"ro.build.version.preview_sdk={option.platform_preview_sdk_version}") + print(f"ro.build.version.preview_sdk_fingerprint={platform_preview_sdk_fingerprint}") + print(f"ro.build.version.codename={option.platform_version_codename}") + print(f"ro.build.version.all_codenames={','.join(option.platform_version_all_codenames)}") + print(f"ro.build.version.known_codenames={option.platform_version_known_codenames}") + print(f"ro.build.version.release={option.platform_version_last_stable}") + print(f"ro.build.version.release_or_codename={option.platform_version}") + print(f"ro.build.version.release_or_preview_display={option.platform_display_version}") + print(f"ro.build.version.security_patch={option.platform_security_patch}") + print(f"ro.build.version.base_os={option.platform_base_os}") + print(f"ro.build.version.min_supported_target_sdk={option.platform_min_supported_target_sdk_version}") + print(f"ro.build.date={date}") + print(f"ro.build.date.utc={date_utc}") + print(f"ro.build.type={option.build_variant}") + print(f"ro.build.user={option.build_username}") + print(f"ro.build.host={build_hostname}") + # TODO: Remove any tag-related optional property declarations once the goals + # from go/arc-android-sigprop-changes have been achieved. + print(f"ro.build.tags?={build_version_tags}") + # ro.build.flavor are used only by the test harness to distinguish builds. + # Only add _asan for a sanitized build if it isn't already a part of the + # flavor (via a dedicated lunch config for example). + print(f"ro.build.flavor={option.build_flavor}") + + # These values are deprecated, use "ro.product.cpu.abilist" + # instead (see below). + print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,") + print(f"# use ro.product.cpu.abilist instead.") + print(f"ro.product.cpu.abi={option.cpu_abis[0]}") + if len(option.cpu_abis) > 1: + print(f"ro.product.cpu.abi2={option.cpu_abis[1]}") + + if option.default_locale: + print(f"ro.product.locale={option.default_locale}") + print(f"ro.wifi.channels={' '.join(option.default_wifi_channels)}") + + print(f"# ro.build.product is obsolete; use ro.product.device") + print(f"ro.build.product={option.device}") + + print(f"# Do not try to parse description or thumbprint") + print(f"ro.build.description?={build_desc}") + if option.build_thumbprint_file: + build_thumbprint = option.build_thumbprint_file.read().strip() + print(f"ro.build.thumbprint={build_thumbprint}") + + print(f"# end build properties") + +if __name__ == "__main__": + main() diff --git a/scripts/gen_build_prop.py b/scripts/gen_build_prop.py index 56ce14fef..9ea56cbd2 100644 --- a/scripts/gen_build_prop.py +++ b/scripts/gen_build_prop.py @@ -279,7 +279,7 @@ def append_additional_system_props(args): config = args.config # Add the product-defined properties to the build properties. - if not config["PropertySplitEnabled"] or not config["VendorImageFileSystemType"]: + if config["PropertySplitEnabled"] or config["VendorImageFileSystemType"]: if "PRODUCT_PROPERTY_OVERRIDES" in config: props += config["PRODUCT_PROPERTY_OVERRIDES"] @@ -311,7 +311,6 @@ def append_additional_system_props(args): props.append("ro.postinstall.fstab.prefix=/system") enable_target_debugging = True - enable_dalvik_lock_contention_logging = True if config["BuildVariant"] == "user" or config["BuildVariant"] == "userdebug": # Target is secure in user builds. props.append("ro.secure=1") @@ -321,12 +320,6 @@ def append_additional_system_props(args): # Disable debugging in plain user builds. props.append("ro.adb.secure=1") enable_target_debugging = False - enable_dalvik_lock_contention_logging = False - else: - # Disable debugging in userdebug builds if PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG - # is set. - if config["ProductNotDebuggableInUserdebug"]: - enable_target_debugging = False # Disallow mock locations by default for user builds props.append("ro.allow.mock.location=0") @@ -338,11 +331,10 @@ def append_additional_system_props(args): # Allow mock locations by default for non user builds props.append("ro.allow.mock.location=1") - if enable_dalvik_lock_contention_logging: + if enable_target_debugging: # Enable Dalvik lock contention logging. props.append("dalvik.vm.lockprof.threshold=500") - if enable_target_debugging: # Target is more debuggable and adbd is on by default props.append("ro.debuggable=1") else: @@ -424,7 +416,7 @@ def append_additional_vendor_props(args): # This must not be defined for the non-GRF devices. # The values of the GRF properties will be verified by post_process_props.py if config["BoardShippingApiLevel"]: - props.append(f"ro.board.first_api_level={config['BoardShippingApiLevel']}") + props.append(f"ro.board.first_api_level={config['ProductShippingApiLevel']}") # Build system set BOARD_API_LEVEL to show the api level of the vendor API surface. # This must not be altered outside of build system. @@ -483,9 +475,6 @@ def append_additional_product_props(args): if config["NoBionicPageSizeMacro"]: props.append(f"ro.product.build.no_bionic_page_size_macro=true") - # This is a temporary system property that controls the ART module. The plan is - # to remove it by Aug 2025, at which time Mainline updates of the ART module - # will ignore it as well. # If the value is "default", it will be mangled by post_process_props.py. props.append(f"ro.dalvik.vm.enable_uffd_gc={config['EnableUffdGc']}") |