Android11.0(R) MTK 平台开机logo动态替换(by logo.bin方式)

674 阅读4分钟

实现的效果

客户提供一张格式为 bmp 的开机logo,在 linux 环境下执行制作 logo.bin 脚本文件,

apk 拷贝 logo.bin 文件替换系统原有的bin,然后重启 logo 自动更新。

原理分析

MTK 平台的充电图片和开机logo都是打包到 logo.bin 中的

对应的资源路径在源码 vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo

系统一般预制了很多分辨率文件夹,实际通过 BOOT_LOGO 来确定打包那一个

制作 logo.bin 文件的规则在 rules.mk 中写的很详细

vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo\rules.mk

1、将 BOOT_LOGO 文件夹中的 bmp 图片通过 bmp_to_raw 工具转化为 .raw

具体定义在 vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo\update

2、将上一步转化后所有 raw 文件通过 zpipe 工具压缩成 boot_logo.raw 文件

3、最后调用 mkimage 指令将 boot_logo.raw 文件打包成 logo.bin

弄清楚流程了那就好办了,我们只需要将这几个工具和对应的指令集成到一个 .sh 脚本文件即可。

为什么不直接将这几个工具放到 android 系统里呢???

答案是,不支持,一开始我也是这么想的,那直接将这几个工具指令扔到 /system/bin 目录下,

直接调用不就行了,这样就更方便了。实际尝试后发现,对应的工具必须在 linux 下才能执行。

实现代码

先将 bmp_to_raw、zpipe、mkimage 三个工具找到并拷贝至新建文件夹中,就叫 gccLogoBin 吧

vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo\tool\bmp_to_raw

vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo\tool\zpipe

vendor\mediatek\proprietary\bootable\bootloader\lk\scripts\mkimage

除了这三个工具,还需要 img_hdr_logo.cfg 和 BOOT_LOGO 文件夹对应的所有 raw 文件(在out目录下)

vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo\img_hdr_logo.cfg

out\target\product\tcl98\obj\LK_OBJ\build-tcl98\dev\logo\hdplus1560

img_hdr_logo.cfg 文件用于 mkimage 工具参数,hdplus1560(文件夹名称取决于BOOT_LOGO)用于减少 bmp_to_raw 工具

转换的时间,因为我们只更换开机logo,其它图片资源是不动的,所以只需生成 hdplus1560_uboot.raw

这样 gccLogoBin 文件夹下一共是 6 个文件,因为要加上接下来的 makelogobin.sh

#!/bin/bash

if [ "$1" = "" ]; then
	echo "Please input BOOT_LOGO name,"
	echo "Such as: hdplus1560, hd720,wqxga"
	exit
fi

BASELOGO=$1
BOOT_LOGO_RESOURCE=boot_logo.raw
echo "BASELOGO=${BASELOGO}"

# step 1 make hdplus1560_uboot.raw  hdplus1560_kernel.raw
echo "===================step 1 bmp_to_raw make uboot and kernel raw===================="
./bmp_to_raw  ./${BASELOGO}/${BASELOGO}_kernel.raw  logo.bmp
./bmp_to_raw  ./${BASELOGO}/${BASELOGO}_uboot.raw   logo.bmp
echo "=========done"


# step 2 zpipe all raw to boot_logo.raw
echo "===================step 2 zpipe all raws get ${BASELOGO}.raw===================="
./zpipe -l 9 ${BOOT_LOGO_RESOURCE} ./${BASELOGO}/${BASELOGO}_uboot.raw ./${BASELOGO}/${BASELOGO}_battery.raw ./${BASELOGO}/${BASELOGO}_low_battery.raw  ./${BASELOGO}/${BASELOGO}_charger_ov.raw ./${BASELOGO}/${BASELOGO}_num_0.raw ./${BASELOGO}/${BASELOGO}_num_1.raw ./${BASELOGO}/${BASELOGO}_num_2.raw ./${BASELOGO}/${BASELOGO}_num_3.raw ./${BASELOGO}/${BASELOGO}_num_4.raw ./${BASELOGO}/${BASELOGO}_num_5.raw ./${BASELOGO}/${BASELOGO}_num_6.raw ./${BASELOGO}/${BASELOGO}_num_7.raw ./${BASELOGO}/${BASELOGO}_num_8.raw ./${BASELOGO}/${BASELOGO}_num_9.raw ./${BASELOGO}/${BASELOGO}_num_percent.raw ./${BASELOGO}/${BASELOGO}_bat_animation_01.raw ./${BASELOGO}/${BASELOGO}_bat_animation_02.raw ./${BASELOGO}/${BASELOGO}_bat_animation_03.raw ./${BASELOGO}/${BASELOGO}_bat_animation_04.raw ./${BASELOGO}/${BASELOGO}_bat_animation_05.raw ./${BASELOGO}/${BASELOGO}_bat_animation_06.raw ./${BASELOGO}/${BASELOGO}_bat_animation_07.raw ./${BASELOGO}/${BASELOGO}_bat_animation_08.raw ./${BASELOGO}/${BASELOGO}_bat_animation_09.raw ./${BASELOGO}/${BASELOGO}_bat_animation_10.raw ./${BASELOGO}/${BASELOGO}_bat_10_01.raw ./${BASELOGO}/${BASELOGO}_bat_10_02.raw ./${BASELOGO}/${BASELOGO}_bat_10_03.raw ./${BASELOGO}/${BASELOGO}_bat_10_04.raw ./${BASELOGO}/${BASELOGO}_bat_10_05.raw ./${BASELOGO}/${BASELOGO}_bat_10_06.raw ./${BASELOGO}/${BASELOGO}_bat_10_07.raw ./${BASELOGO}/${BASELOGO}_bat_10_08.raw ./${BASELOGO}/${BASELOGO}_bat_10_09.raw ./${BASELOGO}/${BASELOGO}_bat_10_10.raw ./${BASELOGO}/${BASELOGO}_bat_bg.raw ./${BASELOGO}/${BASELOGO}_bat_img.raw ./${BASELOGO}/${BASELOGO}_bat_100.raw ./${BASELOGO}/${BASELOGO}_kernel.raw
echo "=========done"


# step 3 make logo.bin
echo "===================step 3 make logo.bin===================="
./mkimage ${BOOT_LOGO_RESOURCE} img_hdr_logo.cfg  > logo.bin
echo "all=========done"

rm  ${BOOT_LOGO_RESOURCE} -rf

注意第二步中的 zpipe 压缩对应的 raw 是有顺序的,具体顺序请参考你的

vendor\mediatek\proprietary\bootable\bootloader\lk\dev\logo\update

cd gccLogoBin

执行 ./makelogobin.sh hdplus1560

这样我们就制作完成 logo.bin 了,如果是工程版本可以直接将 logo.bin push 到 dev/block/platform/bootdevice/by-name/logo

中重启查看即可,或者用烧写工具直接烧录刚刚的 logo.bin 文件。

工作完成了 50% ,接下来我们要在 apk 中将 logo.bin 拷贝至中 dev/block/platform/bootdevice/by-name/logo

apk 拷贝对应代码如下,app 需要配置 android:sharedUserId="android.uid.system" 和加系统签名

int length = 524288;
    public void copyLogoBin() {
        File srcFile = new File("/sdcard/logo.bin");
        String logoPath = "dev/block/platform/bootdevice/by-name/logo";
        Log.e("logo","logoPath="+logoPath);
        File dstFile =  new File(logoPath);
        OutputStream os = null;
        try {
            FileInputStream is = new FileInputStream(srcFile);
            os = new BufferedOutputStream(new FileOutputStream(dstFile, false), length);
            int curSize = 0;
            byte[] data = new byte[length];
            for (int len; (len = is.read(data)) != -1; ) {
                os.write(data, 0, len);
                curSize += len;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            srcFile.delete();
        }
    }

system app 读写 blk_file 出现 selinux 权限问题,根据 log 增加相应权限

type=1400 audit(0.0:2061): avc: denied { write } for name="mmcblk0p29" dev="tmpfs" ino=578 scontext=u:r:system_app:s0 tcontext=u:object_r:logo_block_device:s0 tclass=blk_file permissive=0

type=1400 audit(0.0:2062): avc: denied { open } for path="/dev/block/mmcblk0p29" dev="tmpfs" ino=578 scontext=u:r:system_app:s0 tcontext=u:object_r:logo_block_device:s0 tclass=blk_file permissive=0

type=1400 audit(0.0:2717): avc: denied { getattr } for path="/dev/block/mmcblk0p29" dev="tmpfs" ino=8299 scontext=u:r:system_app:s0 tcontext=u:object_r:logo_block_device:s0 tclass=blk_file permissive=0

device\mediatek\sepolicy\basic\non_plat\system_app.te

增加 allow system_app logo_block_device:blk_file { getattr open read write };

编译时遇到 neverallow 权限解决

system\sepolicy\public\app.te system\sepolicy\prebuilts\api\30.0\public\app.te

注释 373 行 # Block device access. neverallow appdomain dev_type:blk_file { read write };

重新编译烧写后拷贝时报错

W/System.err: java.io.IOException: write failed: EPERM (Operation not permitted)
2021-02-23 08:24:00.589 6373-6373/? W/System.err:     at libcore.io.IoBridge.write(IoBridge.java:544)
2021-02-23 08:24:00.589 6373-6373/? W/System.err:     at java.io.FileOutputStream.write(FileOutputStream.java:392)
2021-02-23 08:24:00.589 6373-6373/? W/System.err:     at java.io.BufferedOutputStream.write(BufferedOutputStream.java:122)
2021-02-23 08:24:00.589 6373-6373/? W/System.err:     at cg.demo.logo.TestActivity.copyLogoBin(TestActivity.java:146)
2021-02-23 08:24:00.589 6373-6373/? W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:409)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at android.view.View.performClick(View.java:7146)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at android.view.View.performClickInternal(View.java:7119)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at android.view.View.access$3500(View.java:803)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at android.view.View$PerformClick.run(View.java:27533)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at android.os.Handler.handleCallback(Handler.java:883)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:100)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at android.os.Looper.loop(Looper.java:214)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7386)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:980)
2021-02-23 08:24:00.590 6373-6373/? W/System.err: Caused by: android.system.ErrnoException: write failed: EPERM (Operation not permitted)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at libcore.io.Linux.writeBytes(Native Method)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at libcore.io.Linux.write(Linux.java:294)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at libcore.io.ForwardingOs.write(ForwardingOs.java:241)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at libcore.io.BlockGuardOs.write(BlockGuardOs.java:416)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at libcore.io.ForwardingOs.write(ForwardingOs.java:241)
2021-02-23 08:24:00.590 6373-6373/? W/System.err:     at libcore.io.IoBridge.write(IoBridge.java:539)
2021-02-23 08:24:00.590 6373-6373/? W/System.err: 	... 16 more

执行 write() 时报错写入失败

修改 vendor\mediatek\proprietary\bootable\bootloader\lk\platform\mt6771\write_protect.c

注释末尾的 //set_write_protect(); 问题解决

MT6765开机LOGO图片的显示原理

MTK logo.bin手动制作