Android12.0 需求开发篇之新增编译device

1. 需求描述

        一般OEM厂商进行开发时,不会和芯片原厂lunch同一个device。因为一款芯片平台上不太可能就做一款产品,一般会做多款产品,就像手机一样,qcom平台上比如865,手机厂商发布865平台手机一般至少2款以上,有的要达到4款甚至更多,那为了代码复用方便,一般不会给某个产品单独拉分支,因为多分支的维护实在太耗费时间和人力。而添加产品自己device就是一个最好的方案。新增device的优势:

(1). 可以实现同芯片平台上,不同产品根据产品形态进行个性化配置,common部分复用,个性化配置则配置在自己添加的device mk。

(2). 子仓库编译过滤,比如有些子仓库中的代码逻辑产品1需要,产品2不需要,那么在该子仓库编译时就可以通过TARGET_DEVICE或者TARGET_PRODUCT进行过滤区分不参与编译,实现上更为灵活。

(3). Android系统层公共部分逻辑有可复用性,降低研发人力维护成本。

2. 需求实现思路

        阅读本部分之前,请先阅读Android框架探索篇之source lunch配置原理篇章,更有利于理解,且流程性的重复内容不再赘述

        RK原始的RKDOC文件夹下有相关新增device的指导文档,但是本文不采用文档描述的方案;原因是按照RKDOC下进行的device新增目录结构不清晰,因为我们相当于OEM厂商角色,所添加的device在目录结构上应该和芯片device做到分离且清晰,RKDOC中的方案是直接把新增device放入到对应rk自己芯片lunch device里面了,这样就导致目录结构上特别不清晰。所以本文不采用RKDOC中方案实现。以一个逻辑图表述的话如下图1所示:, RKDOC的实现逻辑

1 RKDOC方案目录结构

        实际产品device的对应资源都放入了rk3568s目录里,并在里面新创建device文件夹实现。

        实际个人考量后,将相应产品device资源目录分离出来,比如这里以rk3568平台上增加一个device名为lux为例。实际拆分后的目录结构如图2所示:

图2 修改后目录框图

        一般新增的device目录在源码SDK里结构层级按照如下目录添加device/公司名/device名, 这里样例就是device/dami/lux

3. 需求开发

        以篇章Android框架探索篇之source lunch配置原理总结为基础, 核心所必要的文件包含AndroidProduct.mk, lux.mk, BoardConfig.mk,接下来分别给出这几个核心文件的内容以及相应说明。AndroidProduct.mk文件如下图3所示:

PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/lux.mk

COMMON_LUNCH_CHOICES := \
    lux-userdebug \
    lux-user

3 AndroidProduct.mk文件

        COMMON_LUNCH_CHOICES 是被编译框架直接使用get_build_var获取到,进行lunch选项枚举,所以这里我们把自己的产品 lunch添加进去;PRODUCT_MAKEFILES则是在编译框架中进行解析并赋值给all_product_config,并在后续编译框架中得到current_product_makefile, 因为我们的产品名为lux,所以这里的PRODUCT_MAKEFILES中就一定要是lux.mk,因为在编译框架内部会做匹配性检查, 赋值成别的mk会直接报错拦截掉。

        接下来是lux.mk内容,如图4所示:

include device/rockchip/rk368/rk3568_s/rk3568_s.mk
include device/dami/lux/BoardConfig.mk

PRODUCT_NAME := lux
PRODUCT_DEVICE := lux
PRODUCT_BRAND := lux
PRODUCT_MODEL := lux
PRODUCT_MANUFACTURER := dami

4 lux.mk文件内容

        注意因为我们做目录分离了,所以lux.mk上来的第一步就是要包含芯片device的配置,所以需要先包含原来的rk3568_s中的mk文件, 同时也包含自己的BoardConfig.mk文件,之后PRODUCT_NAMEPRODUCT_DEVICE被赋值为lux,同样这两个变量也会被编译系统解析用来做匹配一致性检查。不可以赋值为其他的值。 所以其他模块研发如果想用来进行区分不同产品时,除了可以使用TARGET_PRODUCT, TARGET_DEVICE,也可以使用PRODUCT_NAME, PRODUCT_DEVICE

        这里为了统一PRODUCT_BRANDPRODUCT_MODEL也同样赋值为lux,此刻抛出一个问题,问题1:其他模块研发同事是否可以使用PRODUCT_BRAND或者PRODUCT_MODEL用来作为判断不同产品的依据。反正图中的配置不也都是产品名lux吗?

        答案是不要用,即使一样也不要用;甚至在手机厂是禁止使用PRODUCT_BRAND PRODUCT_MODEL 来区分不同产品标志。为何, 原因就是由编译框架探索篇章可知,PRODUCT_NAME以及PRODUCT_DEVICE在编译框架中被强制用来做匹配性判断,所以这两个值在系统中是绝不会被更改为其他值的,因为只要更改就一定会在lunch阶段报错了,但是PRODUCT_BRANDPRODUCT_MODEL这两个值则不被做强制检查,这也就代表着这两个值是可以被OEM自行定义的。所以不能用来做不同产品区分的依据。

        为何着重突出在手机厂是禁用呢,是因为手机由于产品形态和领域决定,保密性要求比较高,前期研发期间为了保密,PRODUCT_BRAND和PRODUCT_MODEL是会和PRODUCT_NAME保持一致的,因为如果在研发阶段就直接配成产品实际名就会造成泄密风险, 毕竟此时产品刚处于启动阶段,如果直接配置成产品名,则参与研发同事就直接知道目前做的是下一代哪款手机了,泄密风险大大提高;同样这就给刚接触Android开发的同事造成了误导以为PRODUCT_BRAND PRODUCT_MODEL也能用来进行不同产品区分,结果临近发布前,这两个值被修改了,修改成了对应的手机实际品牌,比如Huawai nova, 或者是xiaomi MIX3, 或者oppo findx7等等类似其他Android手机产品;这时之前其他模块同事使用这两个值做filter过滤时的逻辑就出现偏差了。导致原本本该包含进去的功能由于值被修改了使得Android.mk中的判断逻辑被过滤掉仓库功能代码包含不进去,造成质量回溯。

        接下来就是产品的BoardConfig.mk文件,如下图5所示:

BOARD_USES_AB_IMAGE := false

5 BoardConfig.mk

        没有过多需要补充的, 除此之外还有Android.mk以及AndroidBoard.mk文件,AndroidBoard.mk可以直接包含rk3568s中的,Android.mk则是通用格式,内容分别如图6和如图7所示:

include device/rockchip/rk3568/rk3568_s/AndroidBoard.mk

6 AndridBoard.mk

LOCAL_PATH := $(call my-dir)
include $(call all-makefiles-under,$(LOCAL_PATH))

7 Android.mk

        主要文件添加好后,我们需要实际进行自己device编译烧录测试看下系统是否正常。

4.编译问题处理

        上述核心文件添加完成后,进行实际编译时有编译包报错,特此记录。

编译问题1

FAILED: ninja: 'device/dami/lux/bt_vendor.conf', needed by 'out/target/product/lux/vendor/etc/bluetooth/bt_vendor.conf', missing and no known rule to make it

原因分析:

        因为我们自己添加的device也会包含common目录下编译资源,所以common目录下的相关编译逻辑也是同样在运行。关键点如下:

文件路径:

device/rockchip/common/device.mk

关键内容如图8所示:

PRODUCT_COPY_FILES += \
    $(TARGET_DEVICE_DIR)/bt_vendor.conf:/vendor/etc/bluetooth/bt_vendor.conf

8 device.mk内容

        其中TARGET_DEVICE_DIR 在编译框架中会被强制赋值为当前device路径,赋值位置如下图9所示:

文件路径:

build/core/board_config.mk

 TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

9 TARGET_DEVICE_DIR 赋值

        board_config_mk的路径进行分割赋值给TARGET_DEVICE_DIR , 所以当我们lunch自己添加的新device lux时,TARGET_DEVICE_DIR变量的是就是device/dami/lux,并且使用PRODUCT_COPY_FILES 要实现bt_vendor.conf配置文件的copy,而文件源缺失引起报错。

解决措施:

        从之前rk3568s中将对应bt_vendor.conf重新copy一份到lux目录下即可

 编译问题2; 

FAILED: ninja: 'device/dami/lux/media_profiles_default.xml', needed by 'out/target/product/lux/vendor/etc/media_profiles_V1_0.xml', missing and no known rule to make it

原因同问题1不再赘述

5. 测试验证与运行问题处理

         开始整编Android,实际烧录进行测试 

        source build/envsetup.sh

        lunch lux-userdebug

        ./build.sh -UKAup

5.1 运行问题

        烧录后发现卡在Recover阶段不动,抓取日志关键信息如下:

E:[libfs_mgr]ReadFstabFromFile(): cannot open file: '/etc/recovery.fstab': No such file or directory

I:[libfs_mgr]ReadDefaultFstab(): failed to find device default fstab

E:failed to read default fstab

:Check failed: !fstab.empty()

libc: Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 254 (recovery), pid 254 (recovery)

[  225.150394] init: Service 'recovery' (pid 254) received signal 6

[  225.150456] init: Sending signal 9 to service 'recovery' (pid 254) process group...

[  225.150643] libprocessgroup: Successfully killed process cgroup uid 0 pid 254 in 0ms

[  225.151501] init: Untracked pid 256 exited with status 1

[  230.079919] init: starting service 'recovery'...

[  230.081953] init: Created socket '/dev/socket/recovery', mode 422, user 1000, group 1000

[  230.086966] init: cpuset cgroup controller is not mounted!

E:[libfs_mgr]ReadFstabFromFile(): cannot open file: '/etc/recovery.fstab': No such file or directory

I:[libfs_mgr]ReadDefaultFstab(): failed to find device default fstab

E:Failed to read default fstab

exit=================

        Recovery系统下缺失fstab文件导致无法启动,fstab是包含分区挂载相关信息的配置文件,正常系统启动时由init进程负责解析处理完成相应挂载动作,Recovery模式下则有对应Recovery系统下的相应逻辑进行解析处理。既然没有,那我们就追踪下对应fstab文件在哪里赋值copy的,由于我们是非AB系统,所以仅追踪recovery.fstab即可。

        可以分别在device目录以及build目录下进行快速检测,或者有opengrok也可以检索,最后在build/core目录如下位置检索到:

文件路径:

build/core/Makefile:

关键代码逻辑如图10所示:

recovery_fstab := $(strip $(wildcard $(TARGET_DEVICE_DIR)/recovery.fstab))

图10 recovery_fstab赋值

        可以看到recovery_fstab赋值的位置同样是和 TARGET_DEVICE_DIR变量强相关,这就同样要求我们自己的device下面需要包含文件 recovery.fstab, 既然如此的话,就从rk3568s那侧将对应的非编译框架下文件都copy过来,防止有后续问题。

        修改后重新编译烧录已经正常,device名同步变更且系统启动正常,如图11所示:

11 hsr效果

最后整体修改文件清单如下:

        AndroidBoard.mk  

        Android.mk  

        AndroidProducts.mk  

        BoardConfig.mk  

        bt_vendor.conf  

        config.cfg  

        config.cfg_ab_gki  

        dt-overlay.in  

        lux.mk  

        media_profiles_default.xml  

        ota  

        recovery.fstab  

        recovery.fstab_AB

        其中bt_vendor.conf   config.cfg  config.cfg_ab_gki   dt-overlay.in  media_profiles_default.xml  recovery.fstab  recovery.fstab_AB文件以及ota文件夹由于是从rk3568scopy过来的,内容不必进行展示,仅展示修改以及新增的相关mk文件,patch修改如下图12所示:

diff --git a/lux/Android.mk b/lux/Android.mk
new file mode 100644
index 0000000..7a16792
--- /dev/null
+++ b/lux/Android.mk
@@ -0,0 +1,3 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/lux/AndroidBoard.mk b/lux/AndroidBoard.mk
new file mode 100644
index 0000000..7760ff5
--- /dev/null
+++ b/lux/AndroidBoard.mk
@@ -0,0 +1,3 @@
+# generate fstab file for device
+-include device/rockchip/rk356x/rk3568_s/AndroidBoard.mk
+
diff --git a/lux/AndroidProducts.mk b/lux/AndroidProducts.mk
new file mode 100644
index 0000000..eb30112
--- /dev/null
+++ b/lux/AndroidProducts.mk
@@ -0,0 +1,22 @@
+#
+# Copyright 2014 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.
+#
+
+PRODUCT_MAKEFILES := \
+        $(LOCAL_DIR)/lux.mk
+
+COMMON_LUNCH_CHOICES := \
+    lux-userdebug \
+    lux-user
diff --git a/lux/BoardConfig.mk b/lux/BoardConfig.mk
new file mode 100644
index 0000000..a4b26ca
--- /dev/null
+++ b/lux/BoardConfig.mk
@@ -0,0 +1,19 @@
+#
+# Copyright 2014 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.
+#
+
+# AB image definition
+BOARD_USES_AB_IMAGE := false
diff --git a/lux/lux.mk b/lux/lux.mk
new file mode 100644
index 0000000..174756e
--- /dev/null
+++ b/lux/lux.mk
@@ -0,0 +1,25 @@
+#
+# Copyright 2014 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.
+#
+
+# First lunching is S, api_level is 31
+include device/rockchip/rk356x/rk3568_s/rk3568_s.mk
+include device/dami/lux/BoardConfig.mk
+
+PRODUCT_NAME := lux
+PRODUCT_DEVICE := lux
+PRODUCT_BRAND := lux
+PRODUCT_MODEL := lux
+PRODUCT_MANUFACTURER := dami

12 相关device/dami/lux目录下 patch如图12所示

6. 总结

        补充一点,新增device满足了在编译阶段进行不同产品的区分,那如果研发想在程序运行阶段进行不同产品区分要如何来实现呢?这个就需要另外一套独立的方案去实现了,一般芯片厂家或者OEM开发厂能够支持HWIDproductID功能, HWID用来区分同产品不同批次,productID就用来在程序运行阶段在同芯片平台上区分不同产品, 当然这需要在对应主板上多个产品中同个gpio上的引脚设计不同,比如外接的电阻阻值不同或者其他硬件实现,这样在uboot启动阶段就能通过电压落域区间得出不同产品名,进而设计方案透传到内核,之后到Android系统层,在系统层就可以使用property等属性方式来区分,这部分HWID or PRODUCTID RKDOC中有相似介绍,读者可自行阅读。

        新增编译device需求至此结束,如有不当,欢迎指正。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洋仔518

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值