铁佛 发表于 2025-1-1 15:13:05

Android14 应用APP动态修改开机动画流程

思绪


[*] Android 应用通过下载或者预载入的方式获取开机动画资源文件
[*] 分析开机动画bootanim进程源码,获取开机动画文件加载的路径信息
[*] 原生bootanim动画路径是root分组,应用无法访问,修改bootanim的文件加载路径
[*] 更换system分组的路径,让体系应用和bootanim进程均可以执行文件的读写
[*] 应用通过文件操纵将压缩的动画资源包bootanimation.zip放入执行的动画的文件路径中
[*] 开机后bootanim进程访问应用已经写入好的动画资源,openGL执行开机动画的绘制工作
ps:基于AOSP源码和模仿器环境,不对应实际的项目代码和详细硬件装备
动画文件

动画格式

        开机动画是名称为bootanimation.zip的压缩包格式,解压后文件内容如下:
https://i-blog.csdnimg.cn/direct/198fc357a4904f38bb89cd0a4961ac34.png


[*] part0
        打开文件夹part0,图片的格式是.png,存入的格式也应该是.png。图片的分辨率,根据表现屏的分辨率,不能大于表现屏分辨率,定名格式按照如图所示按照数字顺序正确放置图片
https://i-blog.csdnimg.cn/direct/53f4f07c84224dfdab9cd340981e79b9.png


[*] desc.txt
如图所示,第一行1080 1080是图片的分辨率,15是 每秒15帧
p后面第1个参数:1是播放一次, 0表示无穷循环直至开机完成
p后面第2个参数: 数字表示阶段间隔时间,0表示没有间隔时间
p后面第3个参数:为对应的步调文件夹名称
https://i-blog.csdnimg.cn/direct/7f1cddecb4354bf7a35aef3dcd33131e.png

预存储

        将下载好的资源文件bootanimation.zip,通过adb push 的方式放入/sdcard/Movies 下面,该路径支持应用可读写,临时模仿下载资源文件的存放路径,方便测试,目前只放入来两个不同的开机动画资源包,用于demo演示
https://i-blog.csdnimg.cn/direct/b215aa8935fb42e2ad4eead8bfc4d96a.png
源码分析



[*] 开机动画进程源码路径/frameworks/base/cmds/bootanimation
[*] 核心实现方法在BootAnimation.cpp中
        开机动画的默认路径如下,其根目次为/product 、 /system 、 /oem ,adb查看这些路径的group均为root,意味着app无法直接访问该路径下的文件,以是我们必要更换开机动画资源文件的路径
https://i-blog.csdnimg.cn/direct/ba40f5a001c54a858f6e8011808dd201.pnghttps://i-blog.csdnimg.cn/direct/10fd89eab8e84fc7807f0c104b32d24e.png
Bootanim进程编译

编译下令

source build/envsetup.sh
lunch sdk_pc_x86_64-userdebug (AOSP14r1的清华镜像源码,根据自己本地源码环境而定)
make bootanimation
产物

编译乐成后会在如下目次生成两个文件
out/target/product/emulator64_x86_64/system/bin/bootanimation
out/target/product/emulator64_x86_64/system/lib64/libbootaniamtion.so
将bootanimation 、libbootaniamtion.so 分别使用adb push 到对应的/system/bin 、/system/lib64中,重启装备后见效
路径权限修改

路径group选择

https://i-blog.csdnimg.cn/direct/439e278d2283413293209bb2947b81d4.png
        在不新增分区的环境下,选择目前已经存在的体系路径/data,在adb shell 中执行ls -la可以看到/data 路径的group是system组,可以让体系应用和bootanim进程访问,以是我们选择/data/media/ 目次,修改SYSTEM_BOOTANIMATION_FILE值为/data/media/bootaniamtion.zip
https://i-blog.csdnimg.cn/direct/e1b07c606e3b474d8d7d5d5871c5a939.png
selinux权限

通过修改BootAnimation.cpp 代码中的加载路径,会在执行开机后会出现资源文件(/data/media/bootanimation.zip)加载失败题目,分析avc log确认必要修改selinux权限开放进程对资源文件的读写
allow 规则添加

selinux源码路径:/system/sepolicy
如图,根据目次结构可以直接看到/system/sepolicy/public 下面的 bootanim.te(根据名称判断为开机动画进程的selinux 配置文件)和 system_app.te 体系应用进程的seliunx 配置文件,在两个配置文件中分别加上针对
/data/media/ (该路径u:object_r可以在/system/sepolicy/private/file_contexts中查看,如果没有可以自定义)
https://i-blog.csdnimg.cn/direct/4ae3da80ce374ee2a04d1aa24634cb5e.png
路径的权限,详细修改如下,还必要将对应版本(android 14 api-34)的/prebuilts修改一致
allow bootanim media_userdir_file:file { read getattr open map };
allow bootanim media_userdir_file:dir { search read write };
allow bootanim media_rw_data_file:dir { search read write };
allow bootanim media_rw_data_file:file { read getattr open map }; https://i-blog.csdnimg.cn/direct/0cd2c3609c69499b9a0e14758d83f6cf.png

allow system_app media_userdir_file:dir { search read write add_name create remove_name };
allow system_app media_userdir_file:file { create write open getattr unlink };
allow system_app media_rw_data_file:dir { search read write add_name create };  https://i-blog.csdnimg.cn/direct/1fbc57ac73594780a867fb8b0eb7657e.png
办理neverallow冲突

我们修改相干的te文件后,直接编译会出现相干的selinux冲突错误,因为体系默认的neverallow规则和我们新增的allow规则相互抵牾
冲突的neverallow规则路径如下:
/system/sepolicy/public/domain.te
https://i-blog.csdnimg.cn/direct/0b99009acab54f2b9217560c10924fe4.png
/system/sepolicy/private/domain.te
https://i-blog.csdnimg.cn/direct/db43d7637faa4195930941e1d7f25961.png
/system/sepolicy/private/vold.te
https://i-blog.csdnimg.cn/direct/a2b4a72646d544a38a3fae43c7e4f376.png
还必要修改对应版本的/prebuilts下的同名文件,修改内容保持一致即可
编译下令

source build/envsetup.sh
lunch sdk_pc_x86_64-userdebug (AOSP14r1的清华镜像源码,根据自己本地源码环境而定)
make selinux_policy
产物

编译乐成后会在如下两个目次生成对应文件
out/target/product/emulator64_x86_64/vendor/etc/selinux
out/target/product/emulator64_x86_64/system/etc/selinux
将/vendor/etc/selinux 、/system/etc/selinux分别使用adb push 到对应的/system/etc 、/vendor/etc中,重启装备后见效
文件读写权限

        由于动画资源文件和修改后的路径(/data/media)是只读,无法被bootanim进程加载,我们必要在开机阶段针对/data/media 和/data/media/bootanimation.zip 修改文件权限。开机初始化文件init.rc地点的路径:/system/core/rootdir/init.rc
修改内容如下:
https://i-blog.csdnimg.cn/direct/9677a5452d0348e69e79c815cdddd294.png
编译下令

source build/envsetup.sh
lunch sdk_pc_x86_64-userdebug (AOSP14r1的清华镜像源码,根据自己本地源码环境而定)
make -j8
产物

out/target/product/emulator64_x86_64/system-qemu.img
out/target/product/emulator64_x86_64/system/lib64/vendor-qemu.img
out/target/product/emulator64_x86_64/system/lib64/userdata.img
将system-qemu.img 、vendor-qemu.img 修改名称为system.img 、vendor.img 、把这三个文件更换模仿器路径下的同名文件(模仿器路径参考sdk/system-images/android-34/default/x86_64),删除模仿器缓存,重新创建启动模仿器后,修改的init.rc文件,就可以正常见效。
应用部分

        完成路径和权限题目后,应用只必要将之前push 到/sdcard/Movies 下面的bootanimation.zip压缩包通过代码拷贝到/data/media目次即可,详细代码如下:
@SuppressLint("MissingPermission")
@Composable
fun BootAnimationPage(model: BootAnimationViewModel = viewModel()) {
    val info = model.setInfo.observeAsState()
    val sourcePath_1 = "/sdcard/Movies/bootanimation_1.zip"
    val sourcePath_0 = "/sdcard/Movies/bootanimation_0.zip"

    Column(modifier = Modifier
      .fillMaxSize()
      .background(Color.White)) {
      Text(text = "BootAnimation Page " + info.value, color = Color.Red)

      Button(onClick = {
            BootAnimationRepository.instance.setTargetAnimation(sourcePath_0)
      }, content = { Text("设置开机动画0") })
      Button(onClick = {
            BootAnimationRepository.instance.setTargetAnimation(sourcePath_1)
      }, content = { Text("设置开机动画1") })
    }
} https://i-blog.csdnimg.cn/direct/e90914c26ea44795a4738163e02dfdea.png
fun setTargetAnimation(target: String) {
    val from = File(target)
    copyFile(from)
    mSetInfo.postValue(target)
}

private fun copyFile(src: File) {
    val targetPathDir = "/data/media/"
    val targetPath = targetPathDir + "bootanimation.zip"

    val to = File(targetPathDir)
    val isExists = to.exists()
    val path = to.toPath()
    if (!isExists) {
      Files.createDirectory(path)
    }
    val target = File(targetPath)
    val isExistsFile = target.exists()
    val pathFile = target.toPath()
    if (isExistsFile) {
      Files.delete(pathFile)
    }
    Files.createFile(pathFile)
    Files.copy(src.toPath(), pathFile, StandardCopyOption.REPLACE_EXISTING)
}
https://i-blog.csdnimg.cn/direct/0511fbd53457457ebfab253aa3b354d6.png
APP 读写部分非常简朴,demo就不放出了,各人可以自行实现。




免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Android14 应用APP动态修改开机动画流程