适用于x86架构的安卓5.0以上需要root,或者离线改文件,但并非全部适用;本文仅为个人经验,未涵盖的地方需要自行探索。
手动移植Android x86的arm兼容库(houdini/ndk_translation):简略思路与移植演示_哔哩哔哩_bilibili
简略版以及移植演示,请参考上边视频。需要了解一些东西的初步概念以理解本文再谨慎动手实践,若不了解,请先在模拟环境测试环境下尝试,备份资料。
Houdini兼容库(Intel)与NDK_Translation兼容库(Google)是目前x86处理器运行安卓时兼容arm应用的两种方案。本篇文章参考安卓x86各处的源码,Android-x86项目与Bliss-x86项目的一些文件,还有bliss os开发人员写的兼容库配置脚本(https://github.com/casualsnek/waydroid_script/blob/main/waydroid_extras.py)以尝试实现手动移植这些兼容库。(若要在编译x86安卓时包含兼容库,请移步其他教程)
网上已经存在Android-x86项目的arm兼容启用教程,特别对于在sfs格式的只读system系统目录情况,本篇文章将不适用,请移步网上教程。
其中有些网上的教程还会配置L3级别的widevine,这里不讲。
简述waydroid的脚本的配置过程(install_houdini()与install_ndk()部分):
-
挂载系统镜像,下载压缩包验证解压,扩容镜像(waydroid部分不详述)
-
设置兼容库文件权限为可执行
-
复制文件到系统镜像 ①
-
添加内容到build.prop ③
-
添加内容到init.rc ②
-
卸载镜像
针对以上三个序号①②③分别展开
①兼容库文件构成
(不同安卓版本的文件可能稍不同,不同的来源也可能目录结构均有不同,因此可有多种,但目录结构是由相关配置或者是动态库的预设位置关联的,因此应尽量与移植来源一致)
兼容库文件权限设置
其中lib和etc目录下,相关的文件夹权限均为drwxr-xr-x (755),相关的文件权限为-rw-r--r-- (644),bin目录下的相关可执行文件权限为-rwxr-xr-x (755)
预先说明:部分目录结构含有以下文件不会列出,会在后边详细说明
以下为兼容库文件如何构成的一些例子,移植时可以尽量参考。同时,部分兼容库可能会存放于vendor中,甚至是各种软链接,需要弄清楚它们关联
图例颜色说明:
一、Houdini(经典目录结构):
二、Houdini(waydroid目录结构,linker在bin的arm文件夹中)
三、Houdini (remix os 5.1版本目录结构,houdini可执行文件以及libhoudini.so动态库在/lib/arm/下;类似的,许多安卓模拟器的houdini均在此文件夹,但libhoudini.so在原位置)
Ndk_Translation,9.0及以上,9.0目前有32位版本,9.0与11.0以上有所不同
四、Ndk_Translation(waydroid目录结构,与11.0类似)
五、Ndk_Translation(9.0版本32位目录结构)
②binfmt_misc注册arm二进制执行文件
关于这个模块,可以阅读https://blog.csdn.net/whatday/article/details/88299482/ 以了解更多。
上边已提前说明部分目录结构包含binfmt_misc,在不同的设备/系统上,这部分的支持可以在超级多的地方,但主要是一个工作:在系统初始化时,将binfmt_misc目录下的那些内容拷贝到/proc/sys/fs/binfmt_misc/register 下进行注册。以下举多种例子:
一、Waydroid配置脚本的内容过程解释:
先找到init.rc(在旧版本中init.rc位于根目录/ramdisk,在新版本中init.rc位于/system/etc/init/hw/),然后将以下内容拷贝进去:
②binfmt_misc注册arm二进制执行文件
关于这个模块,可以阅读https://blog.csdn.net/whatday/article/details/88299482/ 以了解更多。
上边已提前说明部分目录结构包含binfmt_misc,在不同的设备/系统上,这部分的支持可以在超级多的地方,但主要是一个工作:在系统初始化时,将binfmt_misc目录下的那些内容拷贝到/proc/sys/fs/binfmt_misc/register 下进行注册。以下举多种例子:
一、Waydroid配置脚本的内容过程解释:
先找到init.rc(在旧版本中init.rc位于根目录/ramdisk,在新版本中init.rc位于/system/etc/init/hw/),然后将以下内容拷贝进去:
解释以上配置文本:在初始化早期,挂载binfmt_misc;检测具有“启用兼容库的执行=√”这个属性时,注册内容
二、谷歌AS模拟器,安卓9 x86的32位:
system\etc\init\ndk_translation.rc的内容:(与waydroid有些类似)
三、chrome os (部分机型,此内容查看于guybrush机型)
安卓容器根目录中的init.bertha.rc 部分内容:
四、Android-x86项目和Bliss OS等系统,部分安卓模拟器:
可以看到Android-x86项目在系统初始化时将脚本文件enable_nativebridge设置成了一个服务,引入了一个属性persist.sys.nativebridge来控制服务的运行与终止。同时enable_nativebridge中也是关于binfmt_misc的配置。一些模拟器则会改动很多,注册的内容可能还会在其他地方
参考其中一种arm_dyn和arm_exe及其文本内容,
:arm_dyn:M::\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x28::/system/bin/houdini:P
:arm_exe:M::\x7f\x45\x4c\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28::/system/bin/houdini:P
由名字可猜测分别对应动态库和可执行程序,而里边的注册内容尾部也标定了arm代码由哪个文件执行。对于houdini,则指定houdini文件的存放位置;对于ndk翻译库,则指定ndk_translation_program_runner_binfmt_misc文件的存放位置。其余部分详解网上有,移植时基本上照搬即可。在移植翻译库时除了复制这些文件,也应考虑如何适配这个binfmt_misc的注册。
③build.prop, default.prop等系统属性内容配置
1. 参考waydroid配置脚本内容:
2.参考Android-x86配置内容:
3.参考谷歌AS模拟器9.0 x86 32位:
4.参考chrome os,安卓11子系统,ndk翻译器:
总结以上例子:这些属性中,部分属性是可选的,而部分属性是必选,但其位置很可能在各种地方,如default.prop或vendor下的build.prop,以下为这些属性总结:
1.abi列表:根据需要,增加或删除abi,以及调整abi顺序
ro.product.cpu.abilist=x86_64,x86,armeabi-v7a,armeabi,arm64-v8a
ro.product.cpu.abilist32=x86,armeabi-v7a,armeabi
ro.product.cpu.abilist64=x86_64,arm64-v8a
上边中,第一行包含全部abi及优先级(arm64优先级最低),第二第三行分别对应32位abi和64位abi。这几行abi属性影响应用安装与运行,大多数情况,应用安装包根据此处判断是否支持的abi以及优先使用的abi。
2. ro.dalvik.vm.isa.arm64=x86_64和ro.dalvik.vm.isa.arm=x86
这两个,如果含有64位或32位arm翻译库,则prop应包含对应的那行属性,具体作用网上有介绍
3. ro.enable.native.bridge.exec=1
这一行属性是安卓系统启用兼容库的标志,也可能与binfmt_misc在rc文件的的注册代码有关;部分包含64位翻译库的系统包含ro.enable.native.bridge.exec64=1,这应该由系统配置,或者init.rc相关的内容决定其作用,依情况添加
4. ro.dalvik.vm.native.bridge
这一个属性很重要,其后参数代表使用的翻译库名称,指向system的lib或lib64目录下的对应文件。同时这一行属性一般可能在根目录的default.prop,部分系统则在build.prop
其后在目前有三种可能:
①libhoudini.so,使用houdini兼容库
②libndk_translation.so,使用ndk_translation兼容库
③libnb.so,使用Android-x86项目特有的中间层,其动态库位置由源代码指定(详细后讲)
5. persist.sys.nativebridge
Android-x86项目特有的属性,控制enable_nativebridge服务的运行与终止,以及决定libnb是否起作用。在系统设置中有其对应的开关。
6. dalvik.vm.isa.{abi}.variant;dalvik.vm.isa.{abi}.features
一般原系统已定义,不同设备(比如atom处理器的平板)可能会有不同的特殊的参数,模拟器和Android-x86一般都是默认;其中AS模拟器额外添加了arm的属性
7.其他可选
一些尚未知晓其作用的属性,如ro.ndk_translation.version,参考兼容库的移植来源。
额外说明
1. houdini 兼容库存在x,y,z这三种版本,同时具有基本对应的安卓版本,可执行的houdini和libhoudini.so中均可获取版本号。版本号形式举个例子:
Houdini 9.0.5c_y.51331
9.0.5c为大版本号,9对应安卓9;51331为小版本号,可作为区分更细版本。中间的y即代表y版本。含义——
x:32位系统内核的arm32翻译库(x86→arm),
y:64位系统内核的arm32翻译库(x86_64→arm),
z:64位系统内核的arm64翻译库(x86_64→arm64)。
NDK翻译库应该也是这么区分两种32位模式,但是难以辨别,要从移植来源确认是32位还是64位linux内核。
最前边的数字存在特例,安卓7的x版本使用的是houdini 6.1.2d_x,但部分模拟器用的libhoudini.so是7.1.1b_x(安卓9.0也能用houdini8)。此外安卓5存在houdini5.0.*和houdni5.2.*,部分使用houdini5.0.*的英特尔cpu的安卓5设备不能使用houdini5.2.*,原因是那些设备的安卓系统缺少部分源代码,以致不兼容新的houdini5.2.*。改动内容可以参考https://github.com/iConsole/Console-OS_art/commits/consoleos-lollipop
2. 部分包含houdini兼容库的Android-x86系统存在/system/vendor/etc/misc/目录,包含三个文件:
.OEMBlackList
.OEMWhiteList
.ThirdPartySO
其作用在Android-x86源码可查(https://osdn.net/projects/android-x86/scm/git/frameworks-base/commits/280957b03c2c36535975d43ef5c0b0a1b8ad2c87 )需要系统代码支持,
功能简述:含有这些文件的系统,开启了“国产app兼容性检查”。这个检查会将那些有x86库但缺斤少两,或者用arm库以次充好的那些app,均安装arm的版本而不是x86版本。
.OEMWhiteList:对这个名单的app关闭这个检查功能,有x86库就装x86
.OEMBlackList:对这个名单的app强制安装arm版本
.ThirdPartySO:包含第三方库的列表,以供检查
另外,adb调试可以用 adb install --abi {abi名称} {apk路径} 命令以指定abi来安装应用;而Android系统在shell可以用 pm install --abi {abi名称} {apk路径} 命令以指定abi安装应用(pm需要root权限,且低版本安卓的pm没有指定abi的功能)
3. libnb.so库:这是属于Android-x86特有的一个中间层,可以找到其源码。其内容标定了libhoudini.so的存放位置(因此remix os等可以将这个库挪到其他地方);同时源码中含有读取persist.sys.nativebridge属性,以决定是否启用兼容;源码中还含有其他调用兼容库的中间层函数,但目前仅针对houdini优化,因此,若移植ndk_translation则不应使用libnb。
Remix OS的libnb源码:https://github.com/JideTechnology/remixos-device-generic-common/blob/jide_x86_lollipop/nativebridge/src/libnb.cpp
4. 翻译库移植来源:鉴于目前可用的翻译库均是闭源产品,使用应该低调些,在以下地方等等可以提取
Houdini:
①Android-x86项目的下载链接,比如若要下载houdini5_z,则从这个网址以5_z为版本下载
http://dl.android-x86/houdini.php?v=5_z
http://dl.android-x86.org/houdini/5_z/houdini.sfs
②各种市面的安卓模拟器(夜神、雷电、逍遥等等)
③Win11的安卓子系统
④一些Android x86系统,如bliss os,prime os,以前的remix os,凤凰os等等
⑤Intel处理器的chrome os刷机包内的安卓子系统可能含有
⑥寨板、zenfone2手机等intel处理器的安卓设备(Android IA)的刷机包含有
注:houdini自8.0开始就没有发布x版本,8.0仅发布了y版本,10.0则完全没有发布
NDK_Translation:
①谷歌Android Studio模拟器,含有google api的镜像,其中安卓9的x86,安卓11的x86和x86_64,安卓12 x86_64会含有
②部分AMD处理器的chrome os设备的刷机包的安卓子系统会含有
③部分bliss os镜像,waydroid的GitHub资源等等也含有移植过来的翻译库
移植过程大致总结:
1. 获取/提取兼容库,参考兼容库目录文件构成,将文件复制过去,需要注意兼容库版本,目标系统空间剩余
2. 对复制后的兼容库文件/文件夹进行权限设置
3. 配置binfmt_misc,参考上边的过程类似;
常见的有:
①根目录下的init.rc或init.{机型相关}.rc中包含部分注册内容,这些内容将/system/etc/binfmt_misc/下的配置进行注册;
②/system/etc/init/,或/vendor/etc/等附近与init有关的rc文件,也与①类似;
③Android-x86项目已通过init.rc相关的地方将脚本文件/system/bin/enable_nativebridge设置为服务,注册/配置内容均在此脚本文件中实现。(不同的模拟器改动较大,自行探索)
4. 配置属性(default.prop或build.prop等),参考上边内容