• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright (C) 2024 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17"""A tool for generating {partition}/build.prop"""
18
19import argparse
20import contextlib
21import json
22import os
23import subprocess
24import sys
25
26TEST_KEY_DIR = "build/make/target/product/security"
27
28def get_build_variant(product_config):
29  if product_config["Eng"]:
30    return "eng"
31  elif product_config["Debuggable"]:
32    return "userdebug"
33  else:
34    return "user"
35
36def get_build_flavor(product_config):
37  build_flavor = product_config["DeviceProduct"] + "-" + get_build_variant(product_config)
38  if "address" in product_config.get("SanitizeDevice", []) and "_asan" not in build_flavor:
39    build_flavor += "_asan"
40  return build_flavor
41
42def get_build_keys(product_config):
43  default_cert = product_config.get("DefaultAppCertificate", "")
44  if default_cert == "" or default_cert == os.path.join(TEST_KEY_DIR, "testKey"):
45    return "test-keys"
46  return "dev-keys"
47
48def parse_args():
49  """Parse commandline arguments."""
50  parser = argparse.ArgumentParser()
51  parser.add_argument("--build-fingerprint-file", required=True, type=argparse.FileType("r"))
52  parser.add_argument("--build-hostname-file", required=True, type=argparse.FileType("r"))
53  parser.add_argument("--build-number-file", required=True, type=argparse.FileType("r"))
54  parser.add_argument("--build-thumbprint-file", type=argparse.FileType("r"))
55  parser.add_argument("--build-username", required=True)
56  parser.add_argument("--date-file", required=True, type=argparse.FileType("r"))
57  parser.add_argument("--platform-preview-sdk-fingerprint-file", required=True, type=argparse.FileType("r"))
58  parser.add_argument("--prop-files", action="append", type=argparse.FileType("r"), default=[])
59  parser.add_argument("--product-config", required=True, type=argparse.FileType("r"))
60  parser.add_argument("--partition", required=True)
61  parser.add_argument("--build-broken-dup-sysprop", action="store_true", default=False)
62
63  parser.add_argument("--out", required=True, type=argparse.FileType("w"))
64
65  args = parser.parse_args()
66
67  # post process parse_args requiring manual handling
68  args.config = json.load(args.product_config)
69  config = args.config
70
71  config["BuildFlavor"] = get_build_flavor(config)
72  config["BuildKeys"] = get_build_keys(config)
73  config["BuildVariant"] = get_build_variant(config)
74
75  config["BuildFingerprint"] = args.build_fingerprint_file.read().strip()
76  config["BuildHostname"] = args.build_hostname_file.read().strip()
77  config["BuildNumber"] = args.build_number_file.read().strip()
78  config["BuildUsername"] = args.build_username
79
80  build_version_tags_list = config["BuildVersionTags"]
81  if config["BuildType"] == "debug":
82    build_version_tags_list.append("debug")
83  build_version_tags_list.append(config["BuildKeys"])
84  build_version_tags = ",".join(sorted(set(build_version_tags_list)))
85  config["BuildVersionTags"] = build_version_tags
86
87  raw_date = args.date_file.read().strip()
88  config["Date"] = subprocess.check_output(["date", "-d", f"@{raw_date}"], text=True).strip()
89  config["DateUtc"] = subprocess.check_output(["date", "-d", f"@{raw_date}", "+%s"], text=True).strip()
90
91  # build_desc is human readable strings that describe this build. This has the same info as the
92  # build fingerprint.
93  # e.g. "aosp_cf_x86_64_phone-userdebug VanillaIceCream MAIN eng.20240319.143939 test-keys"
94  config["BuildDesc"] = f"{config['DeviceProduct']}-{config['BuildVariant']} " \
95                        f"{config['Platform_version_name']} {config['BuildId']} " \
96                        f"{config['BuildNumber']} {config['BuildVersionTags']}"
97
98  config["PlatformPreviewSdkFingerprint"] = args.platform_preview_sdk_fingerprint_file.read().strip()
99
100  if args.build_thumbprint_file:
101    config["BuildThumbprint"] = args.build_thumbprint_file.read().strip()
102
103  append_additional_system_props(args)
104  append_additional_vendor_props(args)
105  append_additional_product_props(args)
106
107  return args
108
109def generate_common_build_props(args):
110  print("####################################")
111  print("# from generate-common-build-props")
112  print("# These properties identify this partition image.")
113  print("####################################")
114
115  config = args.config
116  build_flags = config["BuildFlags"]
117  partition = args.partition
118
119  if partition == "system":
120    print(f"ro.product.{partition}.brand={config['SystemBrand']}")
121    print(f"ro.product.{partition}.device={config['SystemDevice']}")
122    print(f"ro.product.{partition}.manufacturer={config['SystemManufacturer']}")
123    print(f"ro.product.{partition}.model={config['SystemModel']}")
124    print(f"ro.product.{partition}.name={config['SystemName']}")
125  else:
126    print(f"ro.product.{partition}.brand={config['ProductBrand']}")
127    print(f"ro.product.{partition}.device={config['DeviceName']}")
128    print(f"ro.product.{partition}.manufacturer={config['ProductManufacturer']}")
129    print(f"ro.product.{partition}.model={config['ProductModel']}")
130    print(f"ro.product.{partition}.name={config['DeviceProduct']}")
131
132  if partition != "system":
133    if config["ProductModelForAttestation"]:
134        print(f"ro.product.model_for_attestation={config['ProductModelForAttestation']}")
135    if config["ProductBrandForAttestation"]:
136        print(f"ro.product.brand_for_attestation={config['ProductBrandForAttestation']}")
137    if config["ProductNameForAttestation"]:
138        print(f"ro.product.name_for_attestation={config['ProductNameForAttestation']}")
139    if config["ProductDeviceForAttestation"]:
140        print(f"ro.product.device_for_attestation={config['ProductDeviceForAttestation']}")
141    if config["ProductManufacturerForAttestation"]:
142        print(f"ro.product.manufacturer_for_attestation={config['ProductManufacturerForAttestation']}")
143
144  if config["ZygoteForce64"]:
145    if partition == "vendor":
146      print(f"ro.{partition}.product.cpu.abilist={config['DeviceAbiList64']}")
147      print(f"ro.{partition}.product.cpu.abilist32=")
148      print(f"ro.{partition}.product.cpu.abilist64={config['DeviceAbiList64']}")
149  else:
150    if partition == "system" or partition == "vendor" or partition == "odm":
151      print(f"ro.{partition}.product.cpu.abilist={config['DeviceAbiList']}")
152      print(f"ro.{partition}.product.cpu.abilist32={config['DeviceAbiList32']}")
153      print(f"ro.{partition}.product.cpu.abilist64={config['DeviceAbiList64']}")
154
155  print(f"ro.{partition}.build.date={config['Date']}")
156  print(f"ro.{partition}.build.date.utc={config['DateUtc']}")
157  # Allow optional assignments for ARC forward-declarations (b/249168657)
158  # TODO: Remove any tag-related inconsistencies once the goals from
159  # go/arc-android-sigprop-changes have been achieved.
160  print(f"ro.{partition}.build.fingerprint?={config['BuildFingerprint']}")
161  print(f"ro.{partition}.build.id?={config['BuildId']}")
162  print(f"ro.{partition}.build.tags?={config['BuildVersionTags']}")
163  print(f"ro.{partition}.build.type={config['BuildVariant']}")
164  print(f"ro.{partition}.build.version.incremental={config['BuildNumber']}")
165  print(f"ro.{partition}.build.version.release={config['Platform_version_last_stable']}")
166  print(f"ro.{partition}.build.version.release_or_codename={config['Platform_version_name']}")
167  print(f"ro.{partition}.build.version.sdk={config['Platform_sdk_version']}")
168  print(f"ro.{partition}.build.version.sdk_full={config['Platform_sdk_version_full']}")
169
170def generate_build_info(args):
171  print()
172  print("####################################")
173  print("# from gen_build_prop.py:generate_build_info")
174  print("####################################")
175  print("# begin build properties")
176
177  config = args.config
178  build_flags = config["BuildFlags"]
179
180  # The ro.build.id will be set dynamically by init, by appending the unique vbmeta digest.
181  if config["BoardUseVbmetaDigestInFingerprint"]:
182    print(f"ro.build.legacy.id={config['BuildId']}")
183  else:
184    print(f"ro.build.id?={config['BuildId']}")
185
186  # ro.build.display.id is shown under Settings -> About Phone
187  if config["BuildVariant"] == "user":
188    # User builds should show:
189    # release build number or branch.buld_number non-release builds
190
191    # Dev. branches should have DISPLAY_BUILD_NUMBER set
192    if config["DisplayBuildNumber"]:
193      print(f"ro.build.display.id?={config['BuildId']}.{config['BuildNumber']} {config['BuildKeys']}")
194    else:
195      print(f"ro.build.display.id?={config['BuildId']} {config['BuildKeys']}")
196  else:
197    # Non-user builds should show detailed build information (See build desc above)
198    print(f"ro.build.display.id?={config['BuildDesc']}")
199  print(f"ro.build.version.incremental={config['BuildNumber']}")
200  print(f"ro.build.version.sdk={config['Platform_sdk_version']}")
201  print(f"ro.build.version.sdk_full={config['Platform_sdk_version_full']}")
202  print(f"ro.build.version.preview_sdk={config['Platform_preview_sdk_version']}")
203  print(f"ro.build.version.preview_sdk_fingerprint={config['PlatformPreviewSdkFingerprint']}")
204  print(f"ro.build.version.codename={config['Platform_sdk_codename']}")
205  print(f"ro.build.version.all_codenames={','.join(config['Platform_version_active_codenames'])}")
206  print(f"ro.build.version.known_codenames={config['Platform_version_known_codenames']}")
207  print(f"ro.build.version.release={config['Platform_version_last_stable']}")
208  print(f"ro.build.version.release_or_codename={config['Platform_version_name']}")
209  print(f"ro.build.version.release_or_preview_display={config['Platform_display_version_name']}")
210  print(f"ro.build.version.security_patch={config['Platform_security_patch']}")
211  print(f"ro.build.version.base_os={config['Platform_base_os']}")
212  print(f"ro.build.version.min_supported_target_sdk={build_flags['RELEASE_PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION']}")
213  print(f"ro.build.date={config['Date']}")
214  print(f"ro.build.date.utc={config['DateUtc']}")
215  print(f"ro.build.type={config['BuildVariant']}")
216  print(f"ro.build.user={config['BuildUsername']}")
217  print(f"ro.build.host={config['BuildHostname']}")
218  # TODO: Remove any tag-related optional property declarations once the goals
219  # from go/arc-android-sigprop-changes have been achieved.
220  print(f"ro.build.tags?={config['BuildVersionTags']}")
221  # ro.build.flavor are used only by the test harness to distinguish builds.
222  # Only add _asan for a sanitized build if it isn't already a part of the
223  # flavor (via a dedicated lunch config for example).
224  print(f"ro.build.flavor={config['BuildFlavor']}")
225
226  # These values are deprecated, use "ro.product.cpu.abilist"
227  # instead (see below).
228  print(f"# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete,")
229  print(f"# use ro.product.cpu.abilist instead.")
230  print(f"ro.product.cpu.abi={config['DeviceAbi'][0]}")
231  if len(config["DeviceAbi"]) > 1:
232    print(f"ro.product.cpu.abi2={config['DeviceAbi'][1]}")
233
234  if config["ProductLocales"]:
235    print(f"ro.product.locale={config['ProductLocales'][0]}")
236  print(f"ro.wifi.channels={' '.join(config['ProductDefaultWifiChannels'])}")
237
238  print(f"# ro.build.product is obsolete; use ro.product.device")
239  print(f"ro.build.product={config['DeviceName']}")
240
241  print(f"# Do not try to parse description or thumbprint")
242  print(f"ro.build.description?={config['BuildDesc']}")
243  if "BuildThumbprint" in config:
244    print(f"ro.build.thumbprint={config['BuildThumbprint']}")
245
246  print(f"# end build properties")
247
248def write_properties_from_file(file):
249  # Make and Soong use different intermediate files to build vendor/build.prop.
250  # Although the sysprop contents are same, the absolute paths of these
251  # intermediate files are different.
252  # Print the filename for the intermediate files (files in OUT_DIR).
253  # This helps with validating mk->soong migration of android partitions.
254  filename = os.path.basename(file.name) if file.name.startswith(os.environ.get("OUT_DIR")) else file.name
255  print()
256  print("####################################")
257  print(f"# from {filename}")
258  print("####################################")
259  print(file.read(), end="")
260
261def write_properties_from_variable(name, props, build_broken_dup_sysprop):
262  print()
263  print("####################################")
264  print(f"# from variable {name}")
265  print("####################################")
266
267  # Implement the legacy behavior when BUILD_BROKEN_DUP_SYSPROP is on.
268  # Optional assignments are all converted to normal assignments and
269  # when their duplicates the first one wins.
270  if build_broken_dup_sysprop:
271    processed_props = []
272    seen_props = set()
273    for line in props:
274      line = line.replace("?=", "=")
275      key, value = line.split("=", 1)
276      if key in seen_props:
277        continue
278      seen_props.add(key)
279      processed_props.append(line)
280    props = processed_props
281
282  for line in props:
283    print(line)
284
285def append_additional_system_props(args):
286  props = []
287
288  config = args.config
289
290  # Add the product-defined properties to the build properties.
291  if not config["PropertySplitEnabled"] or not config["VendorImageFileSystemType"]:
292    if "PRODUCT_PROPERTY_OVERRIDES" in config:
293      props += config["PRODUCT_PROPERTY_OVERRIDES"]
294
295  props.append(f"ro.treble.enabled={'true' if config['FullTreble'] else 'false'}")
296  # Set ro.llndk.api_level to show the maximum vendor API level that the LLNDK
297  # in the system partition supports.
298  if config["VendorApiLevel"]:
299    props.append(f"ro.llndk.api_level={config['VendorApiLevel']}")
300
301  # Sets ro.actionable_compatible_property.enabled to know on runtime whether
302  # the allowed list of actionable compatible properties is enabled or not.
303  props.append("ro.actionable_compatible_property.enabled=true")
304
305  # Enable core platform API violation warnings on userdebug and eng builds.
306  if config["BuildVariant"] != "user":
307    props.append("persist.debug.dalvik.vm.core_platform_api_policy=just-warn")
308
309  # Define ro.sanitize.<name> properties for all global sanitizers.
310  for sanitize_target in config["SanitizeDevice"]:
311    props.append(f"ro.sanitize.{sanitize_target}=true")
312
313  # Sets the default value of ro.postinstall.fstab.prefix to /system.
314  #
315  # Device board configs can override this to /product to use a
316  # product-specific fstab.postinstall file (installed to
317  # /product/etc/fstab.postinstall). If not overridden, the
318  # system/extras/cppreopts/fstab.postinstall file (installed to
319  # /system/etc/fstab.postinstall) will be used.
320  # Note: The default fstab.postinstall is generic and may be slower
321  # because it tries different mount options line by line to ensure
322  # compatibility across various devices.
323  #
324  #     PRODUCT_PRODUCT_PROPERTIES += ro.postinstall.fstab.prefix=/product
325  #
326  # It then uses ${ro.postinstall.fstab.prefix}/etc/fstab.postinstall to
327  # mount system_other partition.
328  props.append("ro.postinstall.fstab.prefix=/system")
329
330  enable_target_debugging = True
331  enable_dalvik_lock_contention_logging = True
332  if config["BuildVariant"] == "user" or config["BuildVariant"] == "userdebug":
333    # Target is secure in user builds.
334    props.append("ro.secure=1")
335    props.append("security.perf_harden=1")
336
337    if config["BuildVariant"] == "user":
338      # Disable debugging in plain user builds.
339      props.append("ro.adb.secure=1")
340      enable_target_debugging = False
341      enable_dalvik_lock_contention_logging = False
342    else:
343      # Disable debugging in userdebug builds if PRODUCT_NOT_DEBUGGABLE_IN_USERDEBUG
344      # is set.
345      if config["ProductNotDebuggableInUserdebug"]:
346        enable_target_debugging = False
347
348    # Disallow mock locations by default for user builds
349    props.append("ro.allow.mock.location=0")
350  else:
351    # Turn on checkjni for non-user builds.
352    props.append("ro.kernel.android.checkjni=1")
353    # Set device insecure for non-user builds.
354    props.append("ro.secure=0")
355    # Allow mock locations by default for non user builds
356    props.append("ro.allow.mock.location=1")
357
358  if enable_dalvik_lock_contention_logging:
359    # Enable Dalvik lock contention logging.
360    props.append("dalvik.vm.lockprof.threshold=500")
361
362  if enable_target_debugging:
363    # Target is more debuggable and adbd is on by default
364    props.append("ro.debuggable=1")
365  else:
366    # Target is less debuggable and adbd is off by default
367    props.append("ro.debuggable=0")
368
369  if config["BuildVariant"] == "eng":
370    if "ro.setupwizard.mode=ENABLED" in props:
371      # Don't require the setup wizard on eng builds
372      props = list(filter(lambda x: not x.startswith("ro.setupwizard.mode="), props))
373      props.append("ro.setupwizard.mode=OPTIONAL")
374
375    # b/323566535
376    props.append("init.svc_debug.no_fatal.zygote=true")
377
378  if config["SdkBuild"]:
379    props.append("xmpp.auto-presence=true")
380    props.append("ro.config.nocheckin=yes")
381
382  props.append("net.bt.name=Android")
383
384  # This property is set by flashing debug boot image, so default to false.
385  props.append("ro.force.debuggable=0")
386
387  config["ADDITIONAL_SYSTEM_PROPERTIES"] = props
388
389def append_additional_vendor_props(args):
390  props = []
391
392  config = args.config
393  build_flags = config["BuildFlags"]
394
395  # Add cpu properties for bionic and ART.
396  props.append(f"ro.bionic.arch={config['DeviceArch']}")
397  props.append(f"ro.bionic.cpu_variant={config['DeviceCpuVariantRuntime']}")
398  props.append(f"ro.bionic.2nd_arch={config['DeviceSecondaryArch']}")
399  props.append(f"ro.bionic.2nd_cpu_variant={config['DeviceSecondaryCpuVariantRuntime']}")
400
401  props.append(f"persist.sys.dalvik.vm.lib.2=libart.so")
402  props.append(f"dalvik.vm.isa.{config['DeviceArch']}.variant={config['Dex2oatTargetCpuVariantRuntime']}")
403  if config["Dex2oatTargetInstructionSetFeatures"]:
404    props.append(f"dalvik.vm.isa.{config['DeviceArch']}.features={config['Dex2oatTargetInstructionSetFeatures']}")
405
406  if config["DeviceSecondaryArch"]:
407    props.append(f"dalvik.vm.isa.{config['DeviceSecondaryArch']}.variant={config['SecondaryDex2oatCpuVariantRuntime']}")
408    if config["SecondaryDex2oatInstructionSetFeatures"]:
409      props.append(f"dalvik.vm.isa.{config['DeviceSecondaryArch']}.features={config['SecondaryDex2oatInstructionSetFeatures']}")
410
411  # Although these variables are prefixed with TARGET_RECOVERY_, they are also needed under charger
412  # mode (via libminui).
413  if config["RecoveryDefaultRotation"]:
414    props.append(f"ro.minui.default_rotation={config['RecoveryDefaultRotation']}")
415
416  if config["RecoveryOverscanPercent"]:
417    props.append(f"ro.minui.overscan_percent={config['RecoveryOverscanPercent']}")
418
419  if config["RecoveryPixelFormat"]:
420    props.append(f"ro.minui.pixel_format={config['RecoveryPixelFormat']}")
421
422  if "UseDynamicPartitions" in config:
423    props.append(f"ro.boot.dynamic_partitions={'true' if config['UseDynamicPartitions'] else 'false'}")
424
425  if "RetrofitDynamicPartitions" in config:
426    props.append(f"ro.boot.dynamic_partitions_retrofit={'true' if config['RetrofitDynamicPartitions'] else 'false'}")
427
428  if config["ShippingApiLevel"]:
429    props.append(f"ro.product.first_api_level={config['ShippingApiLevel']}")
430
431  if config["ShippingVendorApiLevel"]:
432    props.append(f"ro.vendor.api_level={config['ShippingVendorApiLevel']}")
433
434  if config["BuildVariant"] != "user" and config["BuildDebugfsRestrictionsEnabled"]:
435    props.append(f"ro.product.debugfs_restrictions.enabled=true")
436
437  # Vendors with GRF must define BOARD_SHIPPING_API_LEVEL for the vendor API level.
438  # This must not be defined for the non-GRF devices.
439  # The values of the GRF properties will be verified by post_process_props.py
440  if config["BoardShippingApiLevel"]:
441    props.append(f"ro.board.first_api_level={config['BoardShippingApiLevel']}")
442
443  # Build system set BOARD_API_LEVEL to show the api level of the vendor API surface.
444  # This must not be altered outside of build system.
445  if config["VendorApiLevel"]:
446    props.append(f"ro.board.api_level?={config['VendorApiLevel']}")
447    if config["VendorApiLevelPropOverride"]:
448      props.append(f"ro.board.api_level={config['VendorApiLevelPropOverride']}")
449
450  # RELEASE_BOARD_API_LEVEL_FROZEN is true when the vendor API surface is frozen.
451  if build_flags["RELEASE_BOARD_API_LEVEL_FROZEN"]:
452    props.append(f"ro.board.api_frozen=true")
453
454  # Set build prop. This prop is read by ota_from_target_files when generating OTA,
455  # to decide if VABC should be disabled.
456  if config["DontUseVabcOta"]:
457    props.append(f"ro.vendor.build.dont_use_vabc=true")
458
459  # Set the flag in vendor. So VTS would know if the new fingerprint format is in use when
460  # the system images are replaced by GSI.
461  if config["BoardUseVbmetaDigestInFingerprint"]:
462    props.append(f"ro.vendor.build.fingerprint_has_digest=1")
463
464  props.append(f"ro.vendor.build.security_patch={config['VendorSecurityPatch']}")
465  props.append(f"ro.product.board={config['BootloaderBoardName']}")
466  props.append(f"ro.board.platform={config['BoardPlatform']}")
467  props.append(f"ro.hwui.use_vulkan={config['UsesVulkan']}")
468
469  if config["ScreenDensity"]:
470    props.append(f"ro.sf.lcd_density={config['ScreenDensity']}")
471
472  if "AbOtaUpdater" in config:
473    props.append(f"ro.build.ab_update={'true' if config['AbOtaUpdater'] else 'false'}")
474    if config["AbOtaUpdater"]:
475      props.append(f"ro.vendor.build.ab_ota_partitions={config['AbOtaPartitions']}")
476
477  config["ADDITIONAL_VENDOR_PROPERTIES"] = props
478
479def append_additional_product_props(args):
480  props = []
481
482  config = args.config
483
484  # Add the system server compiler filter if they are specified for the product.
485  if config["SystemServerCompilerFilter"]:
486    props.append(f"dalvik.vm.systemservercompilerfilter={config['SystemServerCompilerFilter']}")
487
488  # Add the 16K developer args if it is defined for the product.
489  props.append(f"ro.product.build.16k_page.enabled={'true' if config['Product16KDeveloperOption'] else 'false'}")
490
491  props.append(f"ro.product.page_size={16384 if config['TargetBoots16K'] else 4096}")
492
493  props.append(f"ro.build.characteristics={config['AAPTCharacteristics']}")
494
495  if "AbOtaUpdater" in config and config["AbOtaUpdater"]:
496    props.append(f"ro.product.ab_ota_partitions={config['AbOtaPartitions']}")
497
498  # Set this property for VTS to skip large page size tests on unsupported devices.
499  props.append(f"ro.product.cpu.pagesize.max={config['DeviceMaxPageSizeSupported']}")
500
501  if config["NoBionicPageSizeMacro"]:
502    props.append(f"ro.product.build.no_bionic_page_size_macro=true")
503
504  # This is a temporary system property that controls the ART module. The plan is
505  # to remove it by Aug 2025, at which time Mainline updates of the ART module
506  # will ignore it as well.
507  # If the value is "default", it will be mangled by post_process_props.py.
508  props.append(f"ro.dalvik.vm.enable_uffd_gc={config['EnableUffdGc']}")
509
510  config["ADDITIONAL_PRODUCT_PROPERTIES"] = props
511
512def build_system_prop(args):
513  config = args.config
514
515  # Order matters here. When there are duplicates, the last one wins.
516  # TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
517  variables = [
518    "ADDITIONAL_SYSTEM_PROPERTIES",
519    "PRODUCT_SYSTEM_PROPERTIES",
520    # TODO(b/117892318): deprecate this
521    "PRODUCT_SYSTEM_DEFAULT_PROPERTIES",
522  ]
523
524  if not config["PropertySplitEnabled"]:
525    variables += [
526      "ADDITIONAL_VENDOR_PROPERTIES",
527      "PRODUCT_VENDOR_PROPERTIES",
528    ]
529
530  build_prop(args, gen_build_info=True, gen_common_build_props=True, variables=variables)
531
532def build_system_ext_prop(args):
533  config = args.config
534
535  # Order matters here. When there are duplicates, the last one wins.
536  # TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
537  variables = ["PRODUCT_SYSTEM_EXT_PROPERTIES"]
538
539  build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
540
541def build_vendor_prop(args):
542  config = args.config
543
544  # Order matters here. When there are duplicates, the last one wins.
545  # TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
546  variables = []
547  if config["PropertySplitEnabled"]:
548    variables += [
549      "ADDITIONAL_VENDOR_PROPERTIES",
550      "PRODUCT_VENDOR_PROPERTIES",
551      # TODO(b/117892318): deprecate this
552      "PRODUCT_DEFAULT_PROPERTY_OVERRIDES",
553      "PRODUCT_PROPERTY_OVERRIDES",
554    ]
555
556  build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
557
558def build_product_prop(args):
559  config = args.config
560
561  # Order matters here. When there are duplicates, the last one wins.
562  # TODO(b/117892318): don't allow duplicates so that the ordering doesn't matter
563  variables = [
564    "ADDITIONAL_PRODUCT_PROPERTIES",
565    "PRODUCT_PRODUCT_PROPERTIES",
566  ]
567
568  gen_common_build_props = True
569
570  # Skip common /product properties generation if device released before R and
571  # has no product partition. This is the first part of the check.
572  if config["Shipping_api_level"] and int(config["Shipping_api_level"]) < 30:
573    gen_common_build_props = False
574
575  # The second part of the check - always generate common properties for the
576  # devices with product partition regardless of shipping level.
577  if config["UsesProductImage"]:
578    gen_common_build_props = True
579
580  build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
581
582  if config["OemProperties"]:
583    print("####################################")
584    print("# PRODUCT_OEM_PROPERTIES")
585    print("####################################")
586
587    for prop in config["OemProperties"]:
588      print(f"import /oem/oem.prop {prop}")
589
590def build_odm_prop(args):
591  variables = ["ADDITIONAL_ODM_PROPERTIES", "PRODUCT_ODM_PROPERTIES"]
592  build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=variables)
593
594def build_prop(args, gen_build_info, gen_common_build_props, variables):
595  config = args.config
596
597  if gen_common_build_props:
598    generate_common_build_props(args)
599
600  if gen_build_info:
601    generate_build_info(args)
602
603  for prop_file in args.prop_files:
604    write_properties_from_file(prop_file)
605
606  for variable in variables:
607    if variable in config:
608      write_properties_from_variable(variable, config[variable], args.build_broken_dup_sysprop)
609
610def main():
611  args = parse_args()
612
613  with contextlib.redirect_stdout(args.out):
614    match args.partition:
615      case "system":
616        build_system_prop(args)
617      case "system_ext":
618        build_system_ext_prop(args)
619      case "odm":
620        build_odm_prop(args)
621      case "product":
622        build_product_prop(args)
623      case "vendor":
624        build_vendor_prop(args)
625      case "system_dlkm" | "vendor_dlkm" | "odm_dlkm" | "bootimage":
626        build_prop(args, gen_build_info=False, gen_common_build_props=True, variables=[])
627      case _:
628        sys.exit(f"not supported partition {args.partition}")
629
630if __name__ == "__main__":
631  main()
632