Chrome OS是Google公司开发的基于Chrome浏览器的操作系统。本文会讲解Chrome OS对于Android系统支持方面的内容。
- 前言
- 获取Chrome OS源码
- Chrome上的Android应用
- ARC++ 项目
- ARCVM 项目
- 获取 Chrome OS 模拟器
- Chrome OS 中的进程
- 为Chrome OS开发Android应用
- 参考资料与推荐读物
前言
Chrome OS与Android都是Google公司开发的操作系统。前者发布于2011年,后者发布于2008年。
当然,大家可能还知道Google的另外一个操作系统,叫做Fuchsia。在今后的文章中,我们也会谈到。
距离Android发布已经超过10年时间,它在移动互联网时代取得了巨大的成就。与此同时,Chrome浏览器也一样非常的成功。相较而言,Chrome OS却仍然不温不火。
目前,Chrome OS主要在以下几种设备上运行:
- Chromebooks
- Chromeboxes
- Chromebits
本文不想对比Chrome OS或者Android系统那个更好,也不会深入讨论Chrome浏览器或者 Chrome OS的具体实现。只将重心发在Chrome OS对于Android App的支持上。因为对于很多人来说,要么是Android平台的开发者,要么是Android系统的用户。
阅读本文需要对Android系统实现有一定的了解,你可以访问Android官方网站获取相应的知识:
或者阅读我之前写过的一些文章:AndroidAnatomy。
获取Chrome OS源码
通过下面的命令可以获取Chrome OS的源码:
mkdir chromeos
cd chromeos
repo init -u https://chromium.googlesource.com/chromiumos/manifest.git
repo sync
上面的命令会将Chrome OS的源码下载在chromeos目录中。完整的源码大小超过20个G,因此可能需要比较长的时间才能完成下载。
如果你想要编译Chrome OS或者对Chrome OS系统开发有兴趣,下面两个文档是一个比较好的开始。
Chrome上的Android应用
Chrome上对于Android应用的支持经历了三个项目和阶段。
| 项目名称 | 开发时间 | 状态 | 特点 | 其他说明 |
|---|---|---|---|---|
| ARC | 2014年 | 已废弃 | 支持各桌面平台的Chrome浏览器 | 需要Android开发者对接,并存在安全问题 |
| ARC++ | 2016年 | 正在使用 | Chrome OS专用,通过Linux容器运行 | 安全性有所提升,但仍然不够 |
| ARCVM | 2019年 | 开发中 | 独立虚拟机,更加安全 | 不确定是否会与ARC++项目合并 |
ARC是 App/Android Runtime for Chrome 的缩写。
ARCVM 是 ARC Virtual Machine 的缩写。
由于ARC项目已经废弃,因此本文不再讨论。
下面仅对另外两个项目做一些介绍。
ARC++ 项目
前面已经看到,ARC项目是为Chrome浏览器设计的。由于浏览器的安全模型与原生系统有很大差异,因此支持Chrome浏览器的应用需要开发者进行特定的修改。这对应用开发者来说,无疑是增加了负担。
因此ARC++项目的设计目标包括:
- 能够直接访问Google Play商店上的应用
- 尽可能少的修改 Android Framework
- 不破坏Chrome OS安全性
- 维持Chrome的更新模型
在Chrome OS工程中,ARC++项目的源码并非集中在一起,它们分散在多处。
Android container
整体来说,ARC++项目的实现机理是:将Android系统运行在基于Linux namespace的容器中。以此达到与宿主系统(Chrome OS)相隔离的目的。
Linux namespace 是内核提供的一个特性。它通过命名空间的形式将资源隔离,使得不同集合的进程看到不同集合的资源。这项技术也是Linux上容器(例如:lxc 和 docker)实现的基础。
Linux 提供了 7 种类型的命名空间:
- Cgroup
- IPC
- Network
- Mount
- PID
- User
- UTS
关于Linux namespace,读者可以通过下面两个链接了解更多信息:
- Namespaces in operation, part 1: namespaces overview
- Separation Anxiety: A Tutorial for Isolating Your System with Linux Namespaces
run_oci 与 config.json
在 Chrome OS 中,有一个名称为 run_oci 的模块,它是一个小巧的容器运行时,它会读取名称为 config.json 的配置文件来完成Android容器的初始化工作。
config.json 中的描述了需要挂载的文件系统,命名空间,设备节点,cgroup配置以及继承的能力。你可以点击链接查看这个文件中的内容。
Android container的启动与退出
config.json 文件中包含了下面这段配置。
"process": {
"terminal": true,
"user": {
"uid": 0,
"gid": 0,
"additionalGids": [5005]
},
"umask": 0,
"args": [
"/system/bin/init",
"second_stage"
],
"env": [
"INIT_SELINUX_TOOK=1500",
"INIT_STARTED_AT=1000",
"PATH=/sbin:/system/sbin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin"
],
...
对Android有所了解的读者在看到/system/bin/init应该会觉得很熟悉。
在Android系统上,init进程负责了整个系统的启动逻辑。它会读取 /init.rc 文件完成系统的初始化工作,这其中包含启动 Android 系统中最重要的一些进程,例如:zygote,system_server,surfaceflinger等。
如果你不理解这里的内容,请熟悉一下 Android Init Language,或者阅读我之前写过的文章:Android系统启动:init进程与init语言。
Chrome OS 上 Android container 启动和退出的流程如下图所示:

借助于run_oci,可以很方便的控制Android容器的入口。这样无论是在开发阶段还是运行阶段,Android系统和Chrome OS都很好的解耦和分离开了,这也就非常的便于维护。这种做法是我们在做软件设计(尤其是大型软件系统)时非常值得借鉴学习的。
图形系统
在Linux容器的基础上,Android的相关进程都已经启动。接下来还需要对接用户界面的图形系统。
图形系统的内容包括:
- 负责应用窗口的创建
- 负责应用窗口的状态变化(例如:移动,改变尺寸)
- 负责图形内存的分配
- 负责图形的合成
- 负责图形的渲染
- 负责输入事件处理
对于 Android 图形系统不熟悉的读者,可以先看这里的文章:AOSP: Android Graphics Overview。
Android的图形系统结构如下:

在Android系统上,图形系统的主要组件包括:
Gralloc:负责分配图形缓冲。HWComposer:通过硬件确定缓冲合成的最有效方法。SurfaceFlinger:接受来自多个源的数据缓冲,将它们合成并将它们发送到显示器。WindowManager:负责创建和管理窗口。
从Android 4.0开始,Android 应用使用的Canvas API通常都会通过硬件加速。另外,还有一些应用会使用 OpenGL ES,甚至使用更新的 Vulkan 接口。
Android系统上的所有界面都通过 Surface 渲染出来。应用程序借助于 Surface 生成应用的界面,并将图形缓冲放入队列中,这些缓冲队列由SurfaceFlinger处理。在底层,Surface的图形缓冲通过gralloc分配。
对于窗口管理来说,Android N(7.0)已经支持多窗口。在《Android 7.0中的多窗口实现解析》一文中,我们已经了解到,Android 的多窗口支持下面三种模式:
- 分屏模式
- 画中画模式
- Freeform 模式
有了这些背景知识之后便可以继续了解ChromeOS对于Android系统的对接逻辑了。
在 ARC++ 这篇文章中,Chromium 项目的开发者 David Revenman 详细介绍了 ARC++ 的项目实现。
这里是他的演讲资料:《Arc++ Graphics: Rendering, Compositing and Window Management》。
ARC++ 项目中图形系统的整体结构如下图所示:

在 Chrome OS 上,gralloc 和 GLES 驱动使用 DRM(Direct Rendering Manager)来渲染。对于合成,HWComposer先处理所有的Android Surface,然后再交由Chrome OS来与Chrome OS的其他界面一起合成。
对于窗口管理,位置变更和尺寸改变由Android完成,而对于最大化,最小化和全屏由 Chrome OS 完成。
Chrome OS中的输入事件由 Ozone 抽象层完成。它使用 GpuMemoryBuffer 对象来保存在Android端使用gralloc 或在Chrome OS端使用DRM分配的DRM缓冲区。
Exosphere是Chrome OS中的一个组件,它允许其他客户端连接到用户界面。它通过验证所请求的操作来保护Chrome OS免受潜在恶意客户端(如Android应用)的侵害。
Android和Chrome OS借助于Wayland协议来完成窗口管理和输入事件的通信。
Chrome OS 中的相关项目见下面这些链接:
- Ozone Overview
- Wayland implementation for Chromium Ozone classes
- Aura
- components/exo
- wayland/wayland-protocols
ARCVM 项目
虚拟机和容器
在虚拟化技术中,虚拟机和容器是很常见的概念。它们非常相似,但不完全一样。
简单来说,虚拟机是对机器的抽象,而容器是对操作系统的抽象。在实际的运行过程中,每个虚拟机会有独立的操作系统内核。而容器互相之间共享同一个内核。
因此:
- 虚拟机通常更“重”,因为它要占用更多的系统资源。不过好处是每个虚拟机之间隔离得更好,运行在同一个物理机的多个虚拟机,如果其中某一个出现了问题,不会影响其他虚拟机和宿主操作系统。
- 容器通常更“轻”,因为它不需要独立的内核(大家所熟悉的Docker就是一个容器)。但容器的缺点也正是因为它是共享同一个内核:如果某个容器中的进程触及了内核的某个Bug,导致内核出现问题,这将影响整个系统,当然也包括所有运行在这个系统上的容器。
下图是虚拟机(左)和容器(右)的对比图:

Crostini项目
从2018年秋天发布的Chrome OS 69版本开始,用户可以在Chrome OS上面运行Debian Linux,这对于很多技术工作者或者软件开发者来说无疑是极大的方便,有了Linux环境,很多笔记上的工作都可以完成了。
支持这个功能的是Crostini项目。
这个项目的机理是:在Chrome OS的系统上,会运行一个称之为crosvm的虚拟机管理器(类似于QEMU),在这之上来运行Linux虚拟机。
其架构如下图所示:

这个项目包含了很多的术语,如果你浏览Chrome OS的文档你可能会经常看到这些术语:
Cicerone:Chrome OS中的守护进程,用来和容器通信。Concierge:Chrome OS中的守护进程,管理虚拟机和容器的生命周期。crosh:全称是Chrome OS shell,这是Chrome OS上的命令行工具。Crostini:在Chrome OS上提供Linux环境的项目名称。crosvm:Chrome OS上的虚拟机管理器。KVM:全称是Kernel Virtual Machine,这是Linux提供的虚拟机机制。Termina:自定义虚拟机的代码名称。Terminal:获取完整的Linux命令行环境和运行Crostini的公开名称。vsh:虚拟机中的shell。
关于这个项目的更多内容,读者可以阅读下面两个文档:
在这个项目的基础上,出于对系统稳定性和安全性的考虑,Chrome OS的维护者便倾向于将Android的运行环境从容器向虚拟机方向过渡。于是乎有ARCVM(Android Runtime for Chrome OS Virtual Machine)的想法就很自然了。
目前该项目还处于早期的开发阶段,你可以通过Gerrit上的patch了解相关内容:message:arcvm Chromium Gerrit。
另外,ARC++和ARCVM项目今后会怎么样,会不会废除前者合并到后者,目前还不确定。
获取 Chrome OS 模拟器
对于大部分人来说,可能并没有运行 Chrome OS 的物理设备。不过通过 Android Studio 可以获取 Chrome OS 的模拟器镜像。借此来熟悉 Chrome OS 的环境。
目前(2019年7月) Google 只提供了预览版的镜像。也许很快就会更新,想要获取最新信息,请访问: Android Developers: Apps for Chrome OS overview。
在安装好 Android Studio 之后,通过下面的方法可以获取 Chrome OS 的模拟器。
- 打开 Android Studio,选择
Tools > SDK Manager。 - 点击
SDK Update Sitestab。 - 点击
+号,添加 URL 为:https://storage.googleapis.com/chrome_os_emulator/addon2-1.xml,名称随意也可以不填。 - 再次点击
+号,添加 URL 为https://storage.googleapis.com/chrome_os_emulator/sys-img2-1.xml,名称随意也可以不填。 - 点击
Apply。 - 点击
SDK Toolstab然后在列表中选择Chrome OS device。 - 点击
OK就会安装 Chrome OS 的虚拟设备了。 - 重启 Android Studio。
- 在Android Studio中,选择
Tools > AVD Manager。 - 点击
Create Virtual Device便可以在Tablet分类下面看到 Chrome OS 的虚拟机设备:Pixelbook。如下图所示:

当前的 Chrome OS 系统镜像以Android 7.1.1版本为基础,因此还需要下载相应版本的Android Image才能运行。
下载完成之后启动需要通过Google账号进行登录,如下图所示:

登录之后可以上拉任务栏可以看见完整的应用列表。从列表中可以看出,系统中内置了Google的GMS。
当然,这也包括了 Google Play 应用商店。

Chrome OS 中的进程
Chrome OS 的虚拟设备启动之后,我们可以用熟悉的 adb 命令来了解其环境。
首先通过adb shell 进入的系统中。
在登录Google账号之前,系统只启动了部分进程,如下所示:
novato_cheets:/ $ ps
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 8176 2020 0 00000000 S /init
system 2 1 5116 1888 0 00000000 S /system/bin/boot_latch
logd 4 1 11864 3076 0 00000000 S /system/bin/logd
root 5 1 7120 2708 0 00000000 S /system/bin/debuggerd
root 6 1 20060 7964 0 00000000 S /system/bin/vold
root 12 5 6864 412 0 00000000 S debuggerd:signaller
root 19 1 3444 576 0 00000000 S /sbin/healthd
shell 20 1 5064 1872 0 00000000 S /system/bin/bugreportd
system 21 1 6460 2292 0 00000000 S /system/bin/servicemanager
system 22 1 80392 28368 0 00000000 S /system/bin/surfaceflinger
root 23 1 1604804 124292 0 00000000 S zygote
shell 24 1 30528 1260 0 00000000 R /sbin/adbd
shell 279 24 5020 2564 sigsuspend ef676a69 S /system/bin/sh
shell 284 279 6416 2408 0 edd48a69 R ps
一旦登录系统之后,再次通过ps命令便可以看到更多的Andorid进程被启动了。
novato_cheets:/ $ ps
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 8184 2036 0 00000000 S /init
logd 4 1 12376 3056 0 00000000 S /system/bin/logd
root 5 1 7120 2680 0 00000000 S /system/bin/debuggerd
root 6 1 24416 8060 0 00000000 S /system/bin/vold
root 12 5 6864 536 0 00000000 S debuggerd:signaller
root 19 1 3444 572 0 00000000 S /sbin/healthd
shell 20 1 5064 1856 0 00000000 S /system/bin/bugreportd
system 21 1 6460 2400 0 00000000 S /system/bin/servicemanager
system 22 1 83508 28660 0 00000000 S /system/bin/surfaceflinger
root 23 1 1606816 121436 0 00000000 S zygote
arc-tracing 87 1 17120 6160 0 00000000 S /system/bin/arctraceservice
system 88 1 19212 6204 0 00000000 S /system/bin/arcbridgeservice
audioserver 89 1 33740 10176 0 00000000 S /system/bin/audioserver
cameraserver 90 1 29256 11952 0 00000000 S /system/bin/cameraserver
drm 91 1 18572 7932 0 00000000 S /system/bin/drmserver
root 92 1 7020 3640 0 00000000 S /system/bin/installd
keystore 93 1 15400 6600 0 00000000 S /system/bin/keystore
mediacodec 94 1 36464 13688 0 00000000 S media.codec
media 95 1 29224 11092 0 00000000 S /system/bin/mediadrmserver
mediaex 96 1 51584 13404 0 00000000 S media.extractor
media 97 1 55480 14684 0 00000000 S /system/bin/mediaserver
root 100 1 25992 5236 0 00000000 S /system/bin/netd
system 101 1 15084 6448 0 00000000 S /system/bin/gatekeeperd
root 104 1 5600 2176 0 00000000 S /system/xbin/perfprofd
system 107 23 1810244 189396 0 00000000 S system_server
root 112 100 6420 2900 0 00000000 S /system/bin/iptables-restore
root 123 100 6432 2916 0 00000000 S /system/bin/ip6tables-restore
shell 228 1 12096 1124 0 00000000 R /sbin/adbd
u0_a16 275 23 1047744 79796 0 00000000 S com.android.systemui
radio 335 23 1045676 94992 0 00000000 S com.android.phone
u0_a40 351 23 1083856 94600 0 00000000 S org.chromium.arc.home
u0_a28 447 23 1023400 65240 0 00000000 S android.ext.services
u0_a47 500 23 1028860 67876 0 00000000 S org.chromium.arc.backup_settings
u0_a26 511 23 1030168 70180 0 00000000 S org.chromium.arc.crash_collector
u0_a49 532 23 1028964 68004 0 00000000 S org.chromium.arc.cast_receiver
u0_a23 545 23 1033920 70136 0 00000000 S org.chromium.arc.gms
u0_a56 553 23 1026796 62364 0 00000000 S org.chromium.arc.ime
u0_a46 566 23 1028868 68484 0 00000000 S org.chromium.arc.tts
system 586 23 1069980 93040 0 00000000 S org.chromium.arc.applauncher
u0_a30 600 23 1030132 78984 0 00000000 S org.chromium.arc.intent_helper
u0_a66 634 23 1025280 68548 0 00000000 S com.android.printspooler
u0_a13 655 23 1035140 85384 0 00000000 S android.process.acore
...
当然了,启动了更多的进程需要消耗更多的内存。在 Chrome OS 完全启动之后,其消耗的内存还是比较大的,你可以通过 free -h 或者 dumpsys meminfo 命令来查看。
novato_cheets:/ $ free -h
total used free shared buffers
Mem: 3.8G 2.3G 1.5G 3.1M 302M
-/+ buffers/cache: 2.0G 1.8G
Swap: 5.6G 0 5.6G
借助 Android Studio 和 Android 模拟器还有adb命令,我们几乎可以把 Chrome OS 当成与 Android 系统一样来开发应用。
为Chrome OS开发Android应用
虽说运行Chrome OS的设备可以直接访问Google Play商店下载Andorid应用。但是,毕竟运行Chrome OS的设备(更像笔记本电脑)和手机存在较大的差异,因此如果希望应用在Chrome OS上能获得更好的体验,还需要开发者进行一定的优化。
这些优化主要在下面四个方面:

- 更大的屏幕:手机设备的屏幕尺寸通常是 4 ~ 7英寸。而运行Chrome OS的设备通常是10 ~ 15英寸。直接将手机的应用界面放大到大屏幕上使用通常体验都不太好,因为控件的留白和字体的大小通常是不合适的。
- 横屏模式:除了游戏和视屏应用之外,手机上的应用大部分都是竖屏的,而运行Chrome OS的设备通常是类似笔记本电脑的横屏。只支持竖屏将浪费很大的屏幕空间。
- 窗口控制:Android N开始支持多窗口。多窗口中提供了Freeform模式,这使得用户可以自由调整窗口的大小和位置。在桌面电脑上,这是几乎必备的功能。
- 外设支持:对于Chrome OS设备来说,除了触摸屏之外,键盘,鼠标和手写笔是很常见的输入设备。对于一些应用来说(例如:绘图应用),这些硬件的支持将极大的提升用户的使用效率。
关于这部分内容不再继续展开,有兴趣的读者可以查看下面几个链接:
- Android Developer: Apps for Chrome OS overview
- Android Apps for Chromebooks and Large Screen Devices (Google I/O ‘17)
- What’s new in Android apps for Chrome OS (Google I/O ‘18)
- Building Android Apps for the Chrome OS Ecosystem (Google I/O’19)
参考资料与推荐读物
- ChromiumOS Quick Start Guide
- Chromium OS Developer Guide
- Git repositories on chromium
- ARC is a project to run Play Store apps on Chrome OS
- Android Developers: Apps for Chrome OS overview
- LWN.net: ARC++
- Google working on new way to run Android apps in Chrome OS called ‘ARCVM’
- [PDF] Arc++ Graphics: Rendering, Compositing and Window Management
- [PDF] Security Evaluation of App Runtime for Chrome
- Android container in Chrome OS
- Preview virtual Chrome OS devices on the Android Emulator
- Hands-on: Fuchsia OS, meet Chrome — or at least a rudimentary Chromium build [Video]