Android不同设备字符串显示原理和build.prop生成过程

Android不同设备字符串显示原理和build.prop生成过程Android不同设备加载字符串build.prop生成过程

1. 问题背景

        在Android各设备上,同一个字符串ID,通过配置不同的product参数用来显示不同的字符串,这样子就可以用一套代码,不同设备加载不同的字符串资源,显示在不同的终端设备上,呈现给用户的描述就是合理准确的,我们来看看字符串ID是怎么定义的

Android不同设备字符串显示原理和build.prop生成过程

 同一个字符串ID,这里有四种产品型号:平板,手机,其他设备,模拟器,这样子不同的设备上就显示了对应的”关于xx”的字符串。

2. 问题描述

Android不同设备字符串显示原理和build.prop生成过程

        我的设备明明是平板设备,但是显示的是“关于手机”的字符串,明显不对。应该就是产品属性相关的配置项没有配置对,也就是product=”XXX”的值不对。

3. 相关字段

        通过以往的工作经验,涉及的配置项为:ro.build.characteristics= ?

default默认为手机设备。而我手上的设备为平板,我该如何修改呢?

        我们来看看此ro值是位于平板设备的product/build.prop文件中,那此ro属性是如何编译到build.prop文件中来的呢,我们一起来探究下?

4. 加载原理

        涉及到编译脚本文件基本都在 build/make/core/ 此路径下,我们找一下此属性定义的位置:

build/make/core/Makefile 文件中

Android不同设备字符串显示原理和build.prop生成过程

 来看看具体定义内容:

	$(hide) echo "#" >> $@; \
	        echo "# ADDITIONAL PRODUCT PROPERTIES" >> $@; \
	        echo "#" >> $@; \
	        echo "ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)" >> $@;

也就是ro属性的值是变量 TARGET_AAPT_CHARACTERISTICS定义的,接下来看看它是定义的地方: build/make/core/product_config.mk

Android不同设备字符串显示原理和build.prop生成过程

 这段话的意思:

        如果没有定义 PRODUCT_CHARACTERISTICS,则默认为default值,也就是手机产品,如果定义了,则为其定义的产品类型,好了到这里,就知道怎么去配置了,所以最后需要配置

PRODUCT_CHARACTERISTICS :=  tablet 就可以解决啦!

5. product/build.prop 生成过程

Android10的源码路径为:build/make/core/makefile文件

# -----------------------------------------------------------------
# product build.prop
INSTALLED_PRODUCT_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT)/build.prop
$(warning 调试 in Makefile 打印TARGET_OUT_PRODUCT的值: $(TARGET_OUT_PRODUCT))
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_PRODUCT_BUILD_PROP_TARGET)

ifdef TARGET_PRODUCT_PROP
product_prop_files := $(TARGET_PRODUCT_PROP)
else
product_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/product.prop)
$(warning 调试 in Makefile 打印TARGET_DEVICE_DIR的值: $(TARGET_DEVICE_DIR))
endif

FINAL_PRODUCT_PROPERTIES += \
    $(call collapse-pairs, $(PRODUCT_PRODUCT_PROPERTIES) $(ADDITIONAL_PRODUCT_PROPERTIES))
FINAL_PRODUCT_PROPERTIES := $(call uniq-pairs-by-first-component, \
    $(FINAL_PRODUCT_PROPERTIES),=)

$(INSTALLED_PRODUCT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(product_prop_files)
	@echo Target product buildinfo: $@
	@mkdir -p $(dir $@)
	$(hide) echo > $@
ifdef BOARD_USES_PRODUCTIMAGE
	$(hide) $(call generate-common-build-props,product,$@)
endif  # BOARD_USES_PRODUCTIMAGE
	$(hide) $(foreach file,$(product_prop_files), \
	    if [ -f "$(file)" ]; then \
	        echo Target product properties from: "$(file)"; \
	        echo "" >> $@; \
	        echo "#" >> $@; \
	        echo "# from $(file)" >> $@; \
	        echo "#" >> $@; \
	        cat $(file) >> $@; \
	        echo "# end of $(file)" >> $@; \
	    fi;)
	$(hide) echo "#" >> $@; \
	        echo "# ADDITIONAL PRODUCT PROPERTIES" >> $@; \
	        echo "#" >> $@; \
	        echo "ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)" >> $@;
	$(hide) $(foreach line,$(FINAL_PRODUCT_PROPERTIES), \
	    echo "$(line)" >> $@;)
	$(hide) build/make/tools/post_process_props.py $@

$(error 调试 到这里停止)

代码解读:

        1. 首先看了这段代码,内容不多,我们一句一句来分析下,首先把关键的位置加上log,并在结尾加上:$(error 调试 到这里停止), 在工程中编译,就会到这里停止下来。

        2. 编译工程自己加的打印log如下:

build/make/core/Makefile:289: warning: 调试 in Makefile 打印TARGET_OUT_PRODUCT的值 out/target/product/ums512_1h10/product
build/make/core/Makefile:413: warning: 调试 in Makefile 打印TARGET_DEVICE_DIR的值 device/sprd/sharkl5Pro/ums512_1h10
build/make/core/Makefile:497: error: 调试 到这里停止

产品工程为展锐平台:sprd   产品项目名:ums512_1h10

关于在Makefile中如何添加打印log,请移步到我的另外一篇文章:Android源码编译makefile文件的调试方法_broadview_java的博客-CSDN博客

        3.  INSTALLED_PRODUCT_BUILD_PROP_TARGET := $(TARGET_OUT_PRODUCT)/build.prop 这句话表达的意思是:最后编译版本的输出路径为out/target/product/ums512_1h10/product/build.prop

        4. product_prop_files := $(wildcard $(TARGET_DEVICE_DIR)/product.prop) :

        wildcard 是通配符的意思,代码表达的意思:就是遍历device/sprd/sharkl5Pro/ums512_1h10路径下的所有product.prop文件,赋值给product_prop_files变量。

        5. 

FINAL_PRODUCT_PROPERTIES += \
    $(call collapse-pairs, $(PRODUCT_PRODUCT_PROPERTIES) $(ADDITIONAL_PRODUCT_PROPERTIES))

        这段代码里面有个call方法  collapse-pairs 就是函数名,后面带两个参数,我们看看这个函数定义的地方:build/make/core/common/string.mk

###########################################################
## Convert "a=b c= d e = f" into "a=b c=d e=f"
##
## $(1): list to collapse
## $(2): if set, separator word; usually "=", ":", or ":="
##       Defaults to "=" if not set.
###########################################################

define collapse-pairs
$(eval _cpSEP := $(strip $(if $(2),$(2),=)))\
$(strip $(subst $(space)$(_cpSEP)$(space),$(_cpSEP),$(strip \
    $(subst $(_cpSEP), $(_cpSEP) ,$(1)))$(space)))
endef

        就是把 =  : := 赋值的语句,或带有空格的赋值语句,统一格式化为 a=b 得样式

        6. 

FINAL_PRODUCT_PROPERTIES := $(call uniq-pairs-by-first-component, \
    $(FINAL_PRODUCT_PROPERTIES),=)

        这段代码,就是调用 uniq-pairs-by-first-component 函数,同样我们看看定义的地方:

build/make/core/common/string.mk文件中

###########################################################
## Given a list of pairs, if multiple pairs have the same
## first components, keep only the first pair.
##
## $(1): list of pairs
## $(2): the separator word, such as ":", "=", etc.
define uniq-pairs-by-first-component
$(eval _upbfc_fc_set :=)\
$(strip $(foreach w,$(1), $(eval _first := $(word 1,$(subst $(2),$(space),$(w))))\
    $(if $(filter $(_upbfc_fc_set),$(_first)),,$(w)\
        $(eval _upbfc_fc_set += $(_first)))))\
$(eval _upbfc_fc_set :=)\
$(eval _first:=)
endef

        就是去掉重复的赋值语句,只保留第一条

        7. 

$(INSTALLED_PRODUCT_BUILD_PROP_TARGET): $(BUILDINFO_COMMON_SH) $(product_prop_files)
	@echo Target product buildinfo: $@
	@mkdir -p $(dir $@)
	$(hide) echo > $@

        这段代码就是一个target 语句,makefile的语法规则如下:

Android不同设备字符串显示原理和build.prop生成过程

 翻译过来就是:

out/target/product/ums512_1h10/product/build.prop 是由下面2个文件编译生成的:

BUILDINFO_COMMON_SH := build/make/tools/buildinfo_common.sh

 还有device/sprd/sharkl5Pro/ums512_1h10路径下的所有product.prop。

$(hide)  我们来看看  hide这个变量定义的地方: build/make/core/config.mk

hide := @

通常makefile会将其执行的命令行在执行前输出到屏幕上。如果将‘@’添加到命令行前,这个命令将不被make回显出来。
例如:@echo  –hello world—-;    // 屏幕输出       —hello world—-
             echo  –hello world—-;    // 没有@ 屏幕输出    echo  —hello world—- 

       8. 

$(hide) $(foreach file,$(product_prop_files), \
	    if [ -f "$(file)" ]; then \
	        echo Target product properties from: "$(file)"; \
	        echo "" >> $@; \
	        echo "#" >> $@; \
	        echo "# from $(file)" >> $@; \
	        echo "#" >> $@; \
	        cat $(file) >> $@; \
	        echo "# end of $(file)" >> $@; \
	    fi;)

        这段代码通过for循环语句,把4中device/sprd/sharkl5Pro/ums512_1h10路径下的所有product.prop文件的内容重定向输出到同一个product.prop中

         9. 

$(hide) echo "#" >> $@; \
	        echo "# ADDITIONAL PRODUCT PROPERTIES" >> $@; \
	        echo "#" >> $@; \
	        echo "ro.build.characteristics=$(TARGET_AAPT_CHARACTERISTICS)" >> $@;

       这里就是把 ro.build.characteristics属性编译到build.prop文件中,好了,到这里就分析完毕了。

6. product/build.prop 内容

Android不同设备字符串显示原理和build.prop生成过程

 内容如下:

Android不同设备字符串显示原理和build.prop生成过程

我们配置的PRODUCT_CHARACTERISTICS :=  table 属性最终编译生成到product/build.prop 文件中。

7. 总结

       系统生成的system/build.prop  vendor/build.prop  分析方法也同上,首先还是要掌握makefile和shell的基本语法规则,然后也要了解makefile的调试方法,看不懂的地方去打log看,就大致明白其编译过程了。

       

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/34174.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注