思绪
- Android 应用通过下载或者预载入的方式获取开机动画资源文件
- 分析开机动画bootanim进程源码,获取开机动画文件加载的路径信息
- 原生bootanim动画路径是root分组,应用无法访问,修改bootanim的文件加载路径
- 更换system分组的路径,让体系应用和bootanim进程均可以执行文件的读写
- 应用通过文件操纵将压缩的动画资源包bootanimation.zip放入执行的动画的文件路径中
- 开机后bootanim进程访问应用已经写入好的动画资源,openGL执行开机动画的绘制工作
ps:基于AOSP源码和模仿器环境,不对应实际的项目代码和详细硬件装备
动画文件
动画格式
开机动画是名称为bootanimation.zip的压缩包格式,解压后文件内容如下:
打开文件夹part0,图片的格式是.png,存入的格式也应该是.png。图片的分辨率,根据表现屏的分辨率,不能大于表现屏分辨率,定名格式按照如图所示按照数字顺序正确放置图片
如图所示,第一行1080 1080是图片的分辨率,15是 每秒15帧
p后面第1个参数:1是播放一次, 0表示无穷循环直至开机完成
p后面第2个参数: 数字表示阶段间隔时间,0表示没有间隔时间
p后面第3个参数:为对应的步调文件夹名称
预存储
将下载好的资源文件bootanimation.zip,通过adb push 的方式放入/sdcard/Movies 下面,该路径支持应用可读写,临时模仿下载资源文件的存放路径,方便测试,目前只放入来两个不同的开机动画资源包,用于demo演示
源码分析
- 开机动画进程源码路径/frameworks/base/cmds/bootanimation
- 核心实现方法在BootAnimation.cpp中
开机动画的默认路径如下,其根目次为/product 、 /system 、 /oem ,adb查看这些路径的group均为root,意味着app无法直接访问该路径下的文件,以是我们必要更换开机动画资源文件的路径
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选择
在不新增分区的环境下,选择目前已经存在的体系路径/data,在adb shell 中执行ls -la可以看到/data 路径的group是system组,可以让体系应用和bootanim进程访问,以是我们选择/data/media/ 目次,修改SYSTEM_BOOTANIMATION_FILE值为/data/media/bootaniamtion.zip
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 bject_r可以在/system/sepolicy/private/file_contexts中查看,如果没有可以自定义)
路径的权限,详细修改如下,还必要将对应版本(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 };
复制代码
- 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 };
复制代码
办理neverallow冲突
我们修改相干的te文件后,直接编译会出现相干的selinux冲突错误,因为体系默认的neverallow规则和我们新增的allow规则相互抵牾
冲突的neverallow规则路径如下:
/system/sepolicy/public/domain.te
/system/sepolicy/private/domain.te
/system/sepolicy/private/vold.te
还必要修改对应版本的/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
修改内容如下:
编译下令
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") })
- }
- }
复制代码
- 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)
- }
复制代码
APP 读写部分非常简朴,demo就不放出了,各人可以自行实现。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |