月度归档:2020年09月

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

这是我的两篇知乎文章 https://zhuanlan.zhihu.com/p/234397497https://zhuanlan.zhihu.com/p/243981657 的合辑。


最近因为个人问题一直又烦又颓,知乎一直没什么动态,连 OpenPal3 都几个月没更新了。但是从昨晚开始好几个小号想过来打我的脸,原因是我一年之前回答了这个问题:为什么很多人不相信鸿蒙系统是真的?​

姑且不说你们搞清楚我讽刺的点在哪没有,请问你们可以拿现在的剑去圆去年前年吹的 b 吗?作为一个程序员,始终对华为终端在软件上的吹逼行为十分讨厌。而且花粉们似乎已经接受了这样的现实,还觉得“大嘴吹过的皮全都实现了”。这种空手套沸腾的行为,不是华为还真不敢干。论营销,你以为华为在负一层,其实他在第五层。这些人搞得我心态爆炸真的烦,我就想看看鸿蒙 2.0 到底是个什么东西。

一开始大家说华为电视上的鸿蒙 1.0 是安卓套壳,很多人纷纷跳出来说“adb 说明不了问题”,颇有见到胳膊就想到大腿的意味;后来又改了话术,说“按照路线图,1.0 就是安卓套壳。怎么了?”。那按照路线图,请问 2.0 就应该不是安卓套壳吧?

DevEco Studio

所以我去下了 DevEco Studio。需要注意的是,DevEco Studio 并不是新做的,华为之前就有这个东西,是开发安卓的:文档中心​

DevEco 1.0 是用来开发安卓的

我一开始就找错了,这个是1.0。2.0 把安卓的支持“删掉”了,换成了鸿蒙。当然这都没什么问题,用 IDEA 二次开发也没什么问题,只是预防海军把 DevEco 拿来作为鸿蒙早就存在的论据。

工程方面现在支持新建电视、智能手表和半智能手表(个人归类,不喜你对)。电视和智能手表支持 Java 和 Javascript,半智能手表只支持 Javascript。比较关心电视的 Java 实现,所以新建了这个。

package com.example.myapplication;

import com.example.myapplication.slice.MainAbilitySlice;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;

public class MainAbility extends Ability {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setMainRoute(MainAbilitySlice.class.getName());
    }
}

Emmmm…. 虽然我不做安卓,但是很久以前学过一点。这好像跟 Activity 有点像?不过也没关系,毕竟(做)好的 API 设计拿来用用,也不是不行。

下面我就想去看看 Ability 的代码。SDK 里面包含的全是 Stub,我去 OpenHarmony 上也没找到 aafwk 的源代码。只找到了 aafwk-lite,但这个明显不是电视上用的版本。各位海军请不要再随便丢一个链接过来说“鸿蒙已经开源了链接在这你还不服吗”,你们自己有去看过吗?还烦请哪位大佬找到了 aafwk 的源码的话留个言。

模拟器运行

找不到就算了,DevEco 还有一个 HVD 管理器,我想这既然模拟器都有,里面运行时肯定是全的吧?

不过这个 Manager 还需要下一些包才能运行,下载一直磕磕绊绊的出问题。这也导致我现在才把模拟器抱起来。

运行模拟器需要登录华为账号?也罢毕竟我以前用过荣耀手机,华为账号还是有的。然后实名注册了一波回来发现,模拟器运行每次限时 1 小时?大概各位也能猜到了,这模拟器其实是跑在服务器上的,界面再串流串回来!

这就堵住了我想看看模拟器里面内容的想法。也行,我先把 Hello World 跑起来吧。跑了 HelloWorld 起来之后,很快就会有 log 打出来。这个也有别人发过了,各位估计也见过:

嗯?

如果你随便下个断点,还能看到更具体的:

嗯?×2

点开 .shadow class,还可以看到:

可能有点看不清,我贴过来:

嗯?×3

dalvik 出现。以及,编译生成的 hap 是个 zip 吗?

嗯?×4

既有 dex 又有 apk,我们把 apk 再解一下,看看究竟是不是大白腿:

嗯?×5

半智能手表

上面也提到过,半智能手表只能使用 Javascript 开发,这是与电视和智能手表不同的地方。其实它们还有另一个不同之处,就是电视和智能手表支持由在服务器上串流调试,但是半智能手表不行。而且它连本地的模拟器(Emulator)都没有,只有一个用 Node 做的 Simulator:

启动 Simulator 的防火墙弹窗
本地 Node.js 做的的 Simulator

华为目前开源出来的代码,都是 Lite 版本,是基于它 2016 年就开源了的 LiteOS 做的。所以有理由相信,现在只有半智能手表会用 LiteOS 版本的鸿蒙。而且现在连完整的模拟器都没有,只能用 nodejs 顶一下。

结语

所以我觉得到这里可以大胆地做出结论了:

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

以华为在嵌入式领域的积累,花一年多做成 LiteOS + 半智能手表这样的进度是合理的。这个答案 如何看待 9 月 10 日华为发布的鸿蒙 OS 2.0 系统,应用前景如何?

里有一段话,我想摘录在这里:

华为本来有两个选择:
1. 我们被美国制裁了,我们别无他法,我们决心从现在开始,用3到5年的时间,自主研发我们的一套体系,摆脱对美依赖;
2. 我们被美国制裁了,但是我们早就做好了准备,已经掏空安卓,随时能拿出鸿蒙来替代,引起一片沸腾;然后顶着沸腾、质疑和嘲讽暗戳戳的加班加点3到5年,终于拿出东西来。
我始终搞不懂的是,为什么华为选择了方案2,因为华为高管喜欢沸腾?
两种选择反映的其实是一家公司的做事态度,反映的是它的诚信度和责任感。

作者:世界树的影子
链接:https://www.zhihu.com/question/420404904/answer/1465210355
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

说实话,要是我的老板把牛逼吹出去了(难听点说就是造假),但我现在的代码做不到,我会脸上滚烫,生怕谁过来问我说“这个 Feature 是还有问题吗?这里是还有 Bug 吗?”。不知道华为的程序员会不会如此。如果也是这样,我能做的也只是摸摸他们受伤的心灵了。

海军还要如何吹?

我也想了一下,海军还能怎么吹呢?

  • 不管,就是打你的脸了!鸿蒙真的存在!
  • 看到 apk 就想到安卓?鸿蒙兼容安卓,这不是很正常吗?
  • 你知道做操作系统多难吗?不用一些开源的东西,你能做出来?
  • 按照路线图,鸿蒙 2.0 就是这个样子,3.0 明年见。
  • 我只能说鸿蒙是中国的希望

当然,具体鸿蒙是什么里子他们是不会管的,华为是不是吹牛逼他们也不会管的。要是华为不吹了,他们大概反而会失落吧。


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

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

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

HDC:鸿蒙版的 ADB

前两天刷 IT 之家,刚好刷到这篇帖子:[系统] 鸿蒙2.0:API/SDK逆向-模拟器鉴赏-LiteOS对比

原来用鸿蒙版的 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/vdexExtractor​

把 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 的,连源代码级别的兼容都做不到。

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

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