Posted on Leave a comment

Chromium Android工程迁移编译过程

本文从Chromium编译的中间产物入手深入分析、学习Chromium Android版本的工程化定制流程。初始工作依赖于Chromium的ninja、GYP构建系统,在构建完成后基于编译中间产物,迁入Android Studio作为新的构建工程,测试编译发布的过程。

注:这种编译过程除了资源文件外其他编译中间产物,都不可修改,不具备大规模定制化的可能性,仅作为熟悉编译过程和代码结构的学习、测试使用。

前提

Chromium代码结构、Android开发、Android Studio使用

编译Chromium

编译步骤可以参考Chromium团队的文章,可以选择编译目标为chrome_public_apk、content_shell_apk,本文以chrome_public_apk为例。

编译结果APK

在以chrome_public_apk为编译目标后,在经历一段时间后编译完成,在out/***文件夹内就包含了所有的编译结果和编译中间产物,其中apk在apks文件夹内,可以拉取安装一下,除了包名外其他功能与Chrome基本一致,本文的迁移目标就是在Android Studio工程下同样可以编译出这个APK,再探讨后续的源码迁移和定制工作。

工作目录

在out/***文件夹下,我们主要涉及到的文件分为三类:so、jar、resource,各自又来自不同的Chromium模块。

apks—编译目标文件目录

gen—编译过程中间产物,基本不涉及

lib.java—jar文件的主要来源,将不同模块的java文件编译后汇集在这个目录

locale—国际化的资源文件

resource-zips—资源文件的主要来源,也是Android Studio module化的主要依据

lib.unstripped—so文件目录

建立Android Studio工程

由于Chromium原有模块是基于命名空间来管理的,而且Android的R资源文件定义方式与此关联,所以需要通过Android Application、Library module的方式进行区分,同时还需要将Android Support这一类第三方库通过Gradle依赖的方式进行关联,而不是JAR+资源文件的方式。

所以基于Chromium的模块划分方式分为如下几个子module:

app—org.chromium.chrome,主App Application

ui—org.chromium.ui,Android Library

base—org.chromium.base,Android Library

components—com.chromium.components,Android Library

content—org.chromium.content,Android Library

media—org.chromium.media,Android Library

autofill—org.chromium.components.autofill,Android Library

web_contents_delegate_android—org.chromium.components.web_contents_delegate_android,Android Library

third_party—com.chromium.third_party,Android Library

tools—org.chromium.tools,Android Library

url—org.chromium.url,Android Library

builder—org.chromium.build,Android Library

net—org.chromium.net,Android Library

mojo—org.chromium.mojo,Android Library

device—org.chromium.device,Android Library

gpu—org.chromium.gpu,Android Library

printing—org.chromium.printing,Android Library

services—org.chromium.services,Android Library

skia—org.chromium.skia,Android Library

迁移编译后so

lib.unstripped目录下的所有so文件,迁入主工程的jniLibs文件中,并在CMake文件中配置引入,切记。

add_library(xxx SHARED IMPORTED)
set_target_properties(xxx PROPERTIES IMPORTED_LOCATION src/main/jniLibs/${ANDROID_ABI}/libxxx.so)

迁移编译后Jar

lib.java目录下按照已经建立好的Android Library工程分别放入libs目录下,注意仅放入非interface.jar的文件,否则可能导致duplicate class问题,同时注意JAR文件重名问题,建议以多多级目录重命名的方式导入。

迁移编译后Resource

gen/chrome/android/chrome_public_apk目录下的AndroidManifest.xml 拷贝到主工程中

resource_zips目录下也同样按照Android Library工程分别解压放入res目录下,尤其注意覆盖问题,因为同一模块下可能有同名的资源文件。android_deps、gvr目录下的资源文件不引入,后续将通过Gradle依赖方式引入。

除此之外还需要将额外的资源文件引入主工程assets目录中,并且禁用压缩。文件如下:chrome_100_percent.pak

icudtl.dat

resources.pak

snapshot_blob.bin

locales目录(包含目录这一级)

修正工程参数+Gradle

上述步骤做完以后工程不能如期运行,还需要调整几个地方,因为有些java文件是在编译过程中生成的:

gen/chrome/android/chrome_public_apk__build_config_java下的buildConfig.java

此文件主要定义启动参数等信息,这个文件主要参考信息,由于Gradle编译的过程中最终会覆盖这个文件,所以里面的所有参数需要通过Gradle配置进行定义。

gen/chrome/android/chrome_public_apk__native_libraries_java下的NativeLibraries.java

此文件主要定义了需要引入哪些so文件、版本号等信息。

运行编译

这一系列的步骤,可以通过一步步的运行报错进行修正,最后得到正确运行的编译包。最后还是那句话,这只是探索定制化过程的一小小步,Chromium项目庞大,需要长久的深入。

如果只是想体验一下迁移后的结果工程,文末附Github工程

Posted on Leave a comment

Zircon进程对象

概要

一个Zircon进程就是一个程序的实例:一个或者多个线程的指令执行以及一系列的资源。

描述

进程对象是以下资源的一个集合:

一般来说,进程是一系列关联代码的执行直到进程被强制终止或者进程主动退出。

进程属于作业,它可以在资源、权限和生命周期控制的角度将多个进程组合为一个应用程序。

生命周期

一个进程通过 sys_process_create() 系统调用来创建,这个调用没有参数;当主线程终止或者最后一个句柄被关闭时(⚠ 未实现),进程进入终止状态。

下一步, 主程序代码通过 sys_process_load() 加载进入进程,开始调用 sys_process_start()开始执行。

系统调用

  • job_create – 在父作业内创建一个新的作业
  • vmar_map – 在一个地址空间范围上映射内存
  • vmar_protect – 在一个地址空间范围上修改权限
  • vmar_unmap – 在一个地址空间范围上解除内存映射
Posted on Leave a comment

Zircon内核对象

Zircon是基于对象的内核。用户模式下的代码基本上都是通过对象句柄与OS资源交互。句柄可以被认为是某个OS子系统与某个资源之间的活动会话。

Zircon动态地管理着如下资源:

  • 处理器时间
  • 内存和地址空间
  • 设备IO内存
  • 中断
  • 信号和等待

应用层内核对象

IPC

任务

信号

内存和地址空间

等待

驱动层内核对象

内核对象与LK层

许多内核对象封装了一个或者多个LK层结构体,比如线程对象封装了 thread_t,相反通道对就没有封装任何LK层对象。

内核对象生命周期

内核对象可以被重新计数。大多数的内核对象在系统调用时产生,被句柄持有计数等于1时处于活动状态,句柄绑定这个句柄值作为系统调用的输出。句柄对象一旦被附加到句柄表中,它就处于活动状态了。当句柄从关闭(调用sys_close())它们的句柄表中卸载时就会递减内核对象的计数。通常最后一个句柄被关闭时内核对象计数会等于0,此时会触发析构函数的运行。

当引用对象的新句柄被创建或者(某些内核代码)获取直接指针引用时,计数会递增。所以一个内核对象的生命周期可能会比创建它的进程的生命周期还要长。

调度器

内核对象是一个派生自Dispatcher 并实现了方法的C++类。所以你会看到线程对象的代码在 ThreadDispatcher中。有许多代码只关心通用意义上的内核对象,这种情况下你看到的名字就是 fbl::RefPtr<Dispatcher>

内核对象安全

原则上说,内核对象没有内在的安全概念,也不会做安全检查。一个单独的进程可能由于同一对象的不同权限拥有两个不同的句柄。

参考更多:

句柄