鸿蒙 2.0 模拟器里究竟有什么:鸿蒙 Java 运行时简析

鸿蒙 2.0 模拟器里究竟有什么:鸿蒙 Java 运行时简析

距离 9 月 10 号已经过去很多天了,鸿蒙的开水终于逐渐平息。我在 上一篇文章 (饱含了对沸腾人民、沸腾现象的愤怒情绪)中最后的总结是:

电视和智能手表上,完全就是安卓套壳;只有半智能手表,是华为在它 16 年开源出来的 LiteOS 的基础上做出来的。

如果你还对现在电视上的鸿蒙心存幻想,觉得鸿蒙不是安卓、觉得鸿蒙是在兼容安卓、觉得安卓是鸿蒙的子系统,这篇文章会更加清楚明白地告诉你真相;如果你认可了鸿蒙是安卓套壳,那么这篇文章会从技术角度探究一下,这层壳到底有多厚。

HDC:鸿蒙版的 ADB

前两天刷 IT 之家,刚好刷到 @Jyer 的帖子:

[系统] 鸿蒙2.0:API/SDK逆向-模拟器鉴赏-LiteOS对比quan.ithome.com

原来用鸿蒙版的 adb,是可以直接连上 Shell 的… root 之后读取 build.prop,证实了系统就是安卓 10。随便看看,还有大量的安卓包、动态库、目录结构什么的,也能够佐证。

既然能登上 Shell,那也就可以把运行时拉下来,看看鸿蒙的运行时到底是什么样子的。

boot-zframework.z.vdex

直接

grep -Rl ohos /system

看下来一圈,猜测 /system/framework/boot-zframework.z.vdex 就是鸿蒙的 Java 运行时,pull 下来一看确实是。vdex 叫做 pre-validated DEX,是安卓新引进的格式。可以用下面的工具

anestisb/vdexExtractorgithub.com图标

把 vdex 转换回普通的 dex(转换完会有两个 dex)。直接扔进 jadx 就可以反编译了:

很多在 SDK 里面不提供的类,都在这里面

如果跟 SDK 对比一下,会发现很多 SDK 中不存在的类使用了安卓的包。从设计上,大多是使用了 Delegate/Proxy/Adapter 避免了上层代码直接依赖安卓,这也是屏蔽实现细节的常用手段。不难看出,虽然华为在 SDK 剔除掉了安卓的依赖,但现在鸿蒙仍然是在安卓之上做的封装。

鸿蒙的分布式特性

在继续分析这层壳的薄厚之前,我觉得有必要先说一下鸿蒙的分布式特性。看了一圈代码下来,是能够感觉到鸿蒙有自己的设计和想法的。这一段完全来自我对反编译代码的理解,未必完全正确,也代表不了鸿蒙真正的思路。

基本想法是:把 API 做成 RPC Call。

鸿蒙的 Ability,比安卓的 Activity 概念要宽泛一些,更像是一个 Service。比如 Wifi Device 是一个 Ability,Wifi Enhancer 是一个 Ability,Wifi HotSpot 也是一个 Ability,另外还会有一个 Registra 来做服务注册和查询。具体这些 Ability 是由谁提供的不是很重要,毕竟都是 RPC Call,理论上不在本机也可以。在 SDK 这一侧,这些功能会被包装成普通的 API。

当然这些都不是新概念,老旧的 COM 就已经可以统一 RPC Call 和本地 Call、也连带提供服务注册和查询。后端上这种微服务架构也比较常见。不过,把操作系统的 API 也做成这种结构,我确实不清楚现在有其他的系统在做。

鸿蒙的壳,有厚有薄

运行时里面包含了很多的组件,完成度各不相同。我把它们大致归为四类,从上到下完成度递减:

  1. 已经按照上面的设计,做完了 RPC 封装、在 Java SDK 和 Service 一侧都不再依赖安卓组件
  2. Java SDK 一侧已经不再依赖安卓,用 JNI 调用了自己封装的 native library,但是在 native 一侧仍然需要依赖安卓
  3. Java SDK 一侧还是需要依赖安卓组件,但是也有依赖自己封装的 native library
  4. 安卓 API 映射大法

我没有全部看完所有组件。目前看的组件里,只有部分相对较轻、比较独立包能够做到第一类(比如 wifi 和 bluetooth),大多组件都是第二和第三类(包括 Ability/AbilityShell/Agp/Usb等等)。第四类也有,典型的比如 os.ProcessManager。

先举一个第一类的例子吧,比如 WifiEnhancer:

这是个单例,在新建对象的时候会把需要的 AbilityId 传进去存起来。API 都是 Message Passing:

在每个函数最后的 request 里,会使用 AbilityId 去 Registra 里面找相应的 Ability 缓存起来,然后直接对他 Rpc call。

这段代码的反编译有点问题

再举个第二/第三类的例子吧:Agp 是华为自己的自绘组件库,封装了常见的 UI 组件和自绘能力:

components 里是 UI 控件,render 里面是绘图 API

components 和 render 里面都是对自己 native library 的 wrapper。在 SDK 一侧,还是需要有 Adapter 来依赖安卓包;而在 native library 一侧,也还有对安卓的依赖:

libagp.z.so 的导入表

上面是 libagp.z.so 的导入表,对安卓的依赖不多。它还导入了很多 Skia 的方法,基本可以是确定是用 Skia 自绘。Skia 是谷歌开发的图形库,不过是跨平台的,可以不算安卓独有。

下面是 libagp.so 的导入表,还依然有大量的安卓导入函数:

libagp.so 的导入表

其实根据国内每家都有自己的安卓 UI 来看,各厂应该都有类似的库,只是未必直接作为 Java API 提供给 App 使用。所以我就好奇去下了个 DevEco 1.0,华为在 1.0 里面提供了线上的手机模拟器。开了个 P40 Pro (Emui 10),里面也有 libagp。(所以盲猜这个 agp 本来是 Emui 里面的自绘库,在鸿蒙里面做了一些新改动,暴露给了 App。)

(此处应有截图,但是华为的线上模拟器经常点不了允许调试…)

再放一个第四类的吧。不过 ProcessManager 本身足够简单,不需要过度封装:

请原谅我看到这的时候真的笑了…我不是故意的

结语

按照目前的分析,我认为鸿蒙如果真的想完全不依赖安卓,还有很长的路要走,个人乐观估计往后一到两年都会是安卓套壳/基于安卓/安卓魔改的状态。跟大嘴的 PPT 更是差得远,更谈不上已经掏空、随时替代、比安卓快 60%。而且似乎并没有要走 WSL1 的路线,这样改下去,要是未来某一天真的把安卓所有的东西都换掉了,肯定是没办法二进制兼容安卓 App 的,连源代码级别的兼容都做不到。

最后,还是想带一点私货。这几天大概看到了热心群众这样的心路历程:从“鸿蒙横空出世”,到“鸿蒙囊括了安卓”,到“鸿蒙在兼容安卓”,再到“华为是在诈美国”,最后是“你说的都对,但是华为需要群众的沸腾来支持”… 难道现在天道有轮回,再次进入亩产三万斤的时代了吗?

若真是如此,那美帝看我们,跟我们看三哥,恐怕没什么大区别。

编辑于 09-15

文章被以下专栏收录