Ahao's Technical Blog Ahao's Technical Blog
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

阿豪讲Framework

不积跬步无以至千里
首页
  • 001.基础篇
  • 002.玩转AOSP篇
  • 003.学穿Binder篇
  • 004.基础组件篇
  • 005.系统启动过程分析
  • 006.Hal开发入门与实践
  • 007.显示系统
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 基础篇

  • 玩转AOSP篇

  • 学穿Binder篇

  • 基础组件篇

    • 001.Android 平台智能指针使用与分析
    • 002.弱引用 wp 的作用
    • 003.Linux eventfd 原理与实践
    • 004.Linux IO 多路复用 epoll 机制
    • 005.Linux timerfd 的基本使用
    • 006.Android Native Looper 机制
    • 007.Android Java Looper 机制
    • 008.Handler 同步屏障机制
    • 009.IdleHanlder 原理与使用
    • 010.Android 属性系统入门
    • 011.属性文件生成过程分析
    • 012.如何添加系统属性
    • 013.属性与 Selinux
    • 014.属性系统源码分析一
    • 015.属性系统源码分析二
    • 016.属性系统源码分析三
    • 017.Unix Domain Socket 使用解析之 UDP 篇
    • 018.Unix Domain Socket 使用解析之 TCP 篇
    • 019.Android 中的 Unix Domain Socket 使用解析
    • 020.socketpair 使用解析
    • 021.Android 平台日志系统整体框架
    • 022.logd 守护进程初始化过程
    • 023.客户端写日志过程分析
    • 024.logd 写日志过程分析一
    • 025.logd 写日志过程分析二
    • 026.logd 读日志过程分析
    • 027.Android 平台日志丢失问题分析
  • 系统启动过程分析

  • Hal开发入门与实践

  • 显示系统

  • Framework
  • 基础组件篇
阿豪
2023-10-19

011.属性文件生成过程分析

这是一个介绍 Android 属性系统的系列文章:

  • Android 属性系统入门
  • 属性文件生成过程分析 (本文)
  • 如何添加系统属性
  • 属性与 Selinux
  • 属性系统整体框架与启动过程分析
  • 属性读写过程源码分析

上文我们说到,在运行的系统中有很多属性文件:

/default.prop
/data/local.prop
/system/build.prop
/system/product/build.prop
/vendor/build.prop
/vendor/odm/etc/build.prop
/vendor/default.prop
1
2
3
4
5
6
7

那么这些属性文件是从哪里来的呢?

我们先看一下 /system/build.prop 文件的开头:

# begin common build properties
# autogenerated by build/make/tools/buildinfo_common.sh
ro.system.build.date=Fri Oct 13 17:23:40 CST 2023
# ......
1
2
3
4

注释里面说,当前文件由 build/make/tools/buildinfo_common.sh 自动生成,我们去看一下这个 shell 脚本的具体内容:

cat build/make/tools/buildinfo_common.sh

#!/bin/bash

partition="$1"

if [ "$#" -ne 1 ]; then
  echo "Usage: $0 <partition>" 1>&2
  exit 1
fi

echo "# begin common build properties"
echo "# autogenerated by $0"

echo "ro.${partition}.build.date=`$DATE`"
echo "ro.${partition}.build.date.utc=`$DATE +%s`"
echo "ro.${partition}.build.fingerprint=$BUILD_FINGERPRINT"
echo "ro.${partition}.build.id=$BUILD_ID"
echo "ro.${partition}.build.tags=$BUILD_VERSION_TAGS"
echo "ro.${partition}.build.type=$TARGET_BUILD_TYPE"
echo "ro.${partition}.build.version.incremental=$BUILD_NUMBER"
echo "ro.${partition}.build.version.release=$PLATFORM_VERSION"
echo "ro.${partition}.build.version.sdk=$PLATFORM_SDK_VERSION"

echo "ro.product.${partition}.brand=$PRODUCT_BRAND"
echo "ro.product.${partition}.device=$PRODUCT_DEVICE"
echo "ro.product.${partition}.manufacturer=$PRODUCT_MANUFACTURER"
echo "ro.product.${partition}.model=$PRODUCT_MODEL"
echo "ro.product.${partition}.name=$PRODUCT_NAME"

echo "# end common build properties"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

上述脚本中,通过 echo 打印了许多信息。这些信息都进入了文件中,那么调用过程中一定做了重定向操作。

我们在 build/make 中搜索 buildinfo_common.sh,看看哪里使用了这个脚本:

cd build/make
grep -R "buildinfo_common.sh" .

./core/Makefile:BUILDINFO_COMMON_SH := build/make/tools/buildinfo_common.sh
1
2
3
4

可以看到在 build/make/core/Makefile 文件中,脚本的路径赋值给了 BUILDINFO_COMMON_SH 变量。

我们接着搜这个变量:

# 还是在 build/make 目录下
grep -R "BUILDINFO_COMMON_SH" .

./core/Makefile:BUILDINFO_COMMON_SH := build/make/tools/buildinfo_common.sh
./core/Makefile:        bash $(BUILDINFO_COMMON_SH) "$(1)" >> $(2)
./core/Makefile:$(INSTALLED_DEFAULT_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(intermediate_system_build_prop)
./core/Makefile:$(intermediate_system_build_prop): $(BUILDINFO_SH) $(BUILDINFO_COMMON_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(API_FINGERPRINT)
./core/Makefile:$(INSTALLED_VENDOR_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(intermediate_system_build_prop)
./core/Makefile:$(INSTALLED_PRODUCT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(product_prop_files)
./core/Makefile:$(INSTALLED_ODM_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH)
./core/Makefile:$(INSTALLED_PRODUCT_SERVICES_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH)
1
2
3
4
5
6
7
8
9
10
11

注意到第二行的输出 ./core/Makefile: bash $(BUILDINFO_COMMON_SH) "$(1)" >> $(2),这里调用了上面的 shell 脚本

打开文件,看到它是函数 generate-common-build-props-with-product-vars-set 的一部分:

define generate-common-build-props-with-product-vars-set
	BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \
	BUILD_ID="$(BUILD_ID)" \
	BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
	BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \
	DATE="$(DATE_FROM_FILE)" \
	PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
	PLATFORM_VERSION="$(PLATFORM_VERSION)" \
	TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
	bash $(BUILDINFO_COMMON_SH) "$(1)" >> $(2)
endef
1
2
3
4
5
6
7
8
9
10
11

这里用函数的参数做了从定向,我们接着搜,哪里使用这个函数:

grep -R "generate-common-build-props-with-product-vars-set" .

./core/Makefile:        $(call generate-common-build-props-with-product-vars-set,$(1),$(2))
./core/Makefile:define generate-common-build-props-with-product-vars-set
./core/Makefile:                $(call generate-common-build-props-with-product-vars-set,system,$@)
1
2
3
4
5

有两个地方调用了 generate-common-build-props-with-product-vars-set 函数:

我们主要看第二个地方:

# 定义 system_prop_file 变量的值
# system_prop_file 代表了一个 prop 属性文件
ifdef TARGET_SYSTEM_PROP
system_prop_file := $(TARGET_SYSTEM_PROP)
else
system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
endif

# 这里是一个 Makefile 规则
# intermediate_system_build_prop 的值类似于 out/target/product/xxx/obj/ETC/system_build_prop_intermediates/build.prop 是一个中间文件,用于生成最终的 /system/build.prop
$(intermediate_system_build_prop): $(BUILDINFO_SH) $(BUILDINFO_COMMON_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET) $(API_FINGERPRINT)
	@echo Target buildinfo: $@
	@mkdir -p $(dir $@)
	$(hide) echo > $@
ifneq ($(PRODUCT_OEM_PROPERTIES),)
	$(hide) echo "#" >> $@; \
	        echo "# PRODUCT_OEM_PROPERTIES" >> $@; \
	        echo "#" >> $@;
	$(hide) $(foreach prop,$(PRODUCT_OEM_PROPERTIES), \
	    echo "import /oem/oem.prop $(prop)" >> $@;)
endif
	$(hide) PRODUCT_BRAND="$(PRODUCT_SYSTEM_BRAND)" \
	        PRODUCT_MANUFACTURER="$(PRODUCT_SYSTEM_MANUFACTURER)" \
	        PRODUCT_MODEL="$(PRODUCT_SYSTEM_MODEL)" \
	        PRODUCT_NAME="$(PRODUCT_SYSTEM_NAME)" \
	        PRODUCT_DEVICE="$(PRODUCT_SYSTEM_DEVICE)" \
			# 在这里调用 generate-common-build-props-with-product-vars-set 生成中间文件
			# out/target/product/xxx/obj/ETC/system_build_prop_intermediates/build.prop
	        $(call generate-common-build-props-with-product-vars-set,system,$@)
	$(hide) TARGET_BUILD_TYPE="$(TARGET_BUILD_VARIANT)" \
	        TARGET_BUILD_FLAVOR="$(TARGET_BUILD_FLAVOR)" \
	        TARGET_DEVICE="$(TARGET_DEVICE)" \
	        PRODUCT_DEFAULT_LOCALE="$(call get-default-product-locale,$(PRODUCT_LOCALES))" \
	        PRODUCT_DEFAULT_WIFI_CHANNELS="$(PRODUCT_DEFAULT_WIFI_CHANNELS)" \
	        PRIVATE_BUILD_DESC="$(PRIVATE_BUILD_DESC)" \
	        BUILD_ID="$(BUILD_ID)" \
	        BUILD_DISPLAY_ID="$(BUILD_DISPLAY_ID)" \
	        DATE="$(DATE_FROM_FILE)" \
	        BUILD_USERNAME="$(BUILD_USERNAME)" \
	        BUILD_HOSTNAME="$(BUILD_HOSTNAME)" \
	        BUILD_NUMBER="$(BUILD_NUMBER_FROM_FILE)" \
	        BOARD_BUILD_SYSTEM_ROOT_IMAGE="$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)" \
	        AB_OTA_UPDATER="$(AB_OTA_UPDATER)" \
	        PLATFORM_VERSION="$(PLATFORM_VERSION)" \
	        PLATFORM_SECURITY_PATCH="$(PLATFORM_SECURITY_PATCH)" \
	        PLATFORM_BASE_OS="$(PLATFORM_BASE_OS)" \
	        PLATFORM_SDK_VERSION="$(PLATFORM_SDK_VERSION)" \
	        PLATFORM_PREVIEW_SDK_VERSION="$(PLATFORM_PREVIEW_SDK_VERSION)" \
	        PLATFORM_PREVIEW_SDK_FINGERPRINT="$$(cat $(API_FINGERPRINT))" \
	        PLATFORM_VERSION_CODENAME="$(PLATFORM_VERSION_CODENAME)" \
	        PLATFORM_VERSION_ALL_CODENAMES="$(PLATFORM_VERSION_ALL_CODENAMES)" \
	        PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION="$(PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION)" \
	        BUILD_VERSION_TAGS="$(BUILD_VERSION_TAGS)" \
	        $(if $(OEM_THUMBPRINT_PROPERTIES),BUILD_THUMBPRINT="$(BUILD_THUMBPRINT_FROM_FILE)") \
	        TARGET_CPU_ABI_LIST="$(TARGET_CPU_ABI_LIST)" \
	        TARGET_CPU_ABI_LIST_32_BIT="$(TARGET_CPU_ABI_LIST_32_BIT)" \
	        TARGET_CPU_ABI_LIST_64_BIT="$(TARGET_CPU_ABI_LIST_64_BIT)" \
	        TARGET_CPU_ABI="$(TARGET_CPU_ABI)" \
	        TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \
	        bash $(BUILDINFO_SH) >> $@
			# 把 system_prop_file 中的内容写入中间文件
	$(hide) $(foreach file,$(system_prop_file), \
	    if [ -f "$(file)" ]; then \
	        echo Target buildinfo from: "$(file)"; \
	        echo "" >> $@; \
	        echo "#" >> $@; \
	        echo "# from $(file)" >> $@; \
	        echo "#" >> $@; \
	        cat $(file) >> $@; \
	        echo "# end of $(file)" >> $@; \
	    fi;)

	# FINAL_BUILD_PROPERTIES 的值来自 ADDITIONAL_BUILD_PROPERTIES
	# ADDITIONAL_BUILD_PROPERTIES 主要是 PRODUCT_PROPERTY_OVERRIDES 这个变量赋值, 而这个变量就是我们开发时经常用于自定义属性的, 一般在产品配置目录下定义
	# 这里把 FINAL_BUILD_PROPERTIES 中的属性写入中间文件
	$(if $(FINAL_BUILD_PROPERTIES), \
	    $(hide) echo >> $@; \
	            echo "#" >> $@; \
	            echo "# ADDITIONAL_BUILD_PROPERTIES" >> $@; \
	            echo "#" >> $@; )
	$(hide) $(foreach line,$(FINAL_BUILD_PROPERTIES), \
	    echo "$(line)" >> $@;)
	$(hide) build/make/tools/post_process_props.py $@ $(PRODUCT_SYSTEM_PROPERTY_BLACKLIST)

build_desc :=

ifeq (,$(filter true, $(TARGET_NO_KERNEL) $(TARGET_NO_RECOVERY)))
INSTALLED_RECOVERYIMAGE_TARGET := $(PRODUCT_OUT)/recovery.img
else
INSTALLED_RECOVERYIMAGE_TARGET :=
endif

# INSTALLED_BUILD_PROP_TARGET 的值为 out/target/product/xxx/system/build.prop
# 也就是我们最终要生成的文件
$(INSTALLED_BUILD_PROP_TARGET): $(intermediate_system_build_prop) $(INSTALLED_RECOVERYIMAGE_TARGET)
	@echo "Target build info: $@"
	# 这里把中间文件写入到最终文件中,同时剔除 ro.product.first_api_level 相关的行
	$(hide) grep -v 'ro.product.first_api_level' $(intermediate_system_build_prop) > $@
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

以上代码总结一下:

  • 准备好一个中间文件 out/target/product/xxx/obj/ETC/system_build_prop_intermediates/build.prop
  • 调用 buildinfo_common.sh,向中间文件写入数据
  • 把 system_prop_file 中的内容写入中间文件
  • 这里把用户自定义的的属性(PRODUCT_PROPERTY_OVERRIDES)写入中间文件
  • 这里把中间文件写入到最终文件(out/target/product/xxx/system/build.pro)中,同时剔除 ro.product.first_api_level 相关的行

以上就是 /system/build.prop,其他属性文件我们都可以依葫芦画瓢进行分析了。

010.Android 属性系统入门
012.如何添加系统属性

← 010.Android 属性系统入门 012.如何添加系统属性→

最近更新
01
如何调试 SurfaceFlinger
10-05
02
SurfaceFlinger 概述
10-05
03
HWC 接口分析
10-05
更多文章>
Theme by Vdoing | Copyright © 2020-2025 AHao Framework | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式