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内核与LK内核的关系

LK(Little Kernel)是一个为嵌入式应用设计的微系统内核,它为FreeRTOS、ThreadX这样的商业项目提供了一个不错的选择。这些系统仅提供有限的内存、有限的外设和任务集;Zircon运行在那些拥有快速处理器、不定大小内存、能够挂载任意外设的现代手机、PC等末端计算设备上。

Zircon内部构建在LK层之上;Zircon有进程的概念,LK则没有;Zircon的进程构建在LK的线程、内存结构之上。

更多的不同点:

Zircon有一类用户模式的支持,LK没有;

Zircon是一个对象句柄系统,LK没有这个概念;

Zircon有能力安全模型,在LK里所有代码都是被信任的。

随着时间的推移,为了满足新的需求、更好的适应上层系统,低层次的结构也可能会改变。

原文链接:

https://fuchsia.googlesource.com/zircon/+/HEAD/docs/zx_and_lk.md

延伸:

LK:

https://github.com/littlekernel/lk/wiki/Introduction

LK内核正在被使用的场景:Android的bootloader和Trusted Execution Environment

Posted on Leave a comment

Android共享热点IP问题引发的“血案”

今天一朋友问Android手机的Wi-Fi共享热点IP能不能修改,他那边一直是192.168.43.*,自己记得在设置里面没有这个选项,便回复了他不能修改。后来猜测Android源码可能为了刻意避开常用局域网路由器192.168.0/1/2.*段,特意设置的其他网段,但会不会存在与基站代理在一个网段后冲突自我协调的机制呢?(当然这个可能性很低,一般基站的代理服务器分配的都是10.*段的内网地址),既然有了这个问题,那索性看看源码怎么设置的。

  • 涉水

首先想到的是到StackOverFlow上看看有没有相关问题,搜索得之,

http://stackoverflow.com/a/31238229/4865380

确实有人提到修改Hotspot网关的问题,给出的具体源码是在WiFiStateMachine.java中硬编码了192.168.43.1这个网关地址,这就解释了为什么共享出去的IP地址都是192.168.43.*了。手机用户想修改它,duang然是不可能了。

  • 挣扎

从AOSP的master中去查找上文提到的platform/framework/base/wifi/java/android/net/WiFiStateMachine.java却消失了踪影,寻寻觅觅发现已经被移到platform/framework/opt/net/wifi/service/java/com/android/server/wifi/WiFiStateMachine.java。一看就对源码分析不熟悉,这些模块搬家的消息都不知道,其实从5.0之后opt/net/wifi之后就有了,部分代码被迁移到这里。

但是,但是,这个文件里面再也没有发现startTethering()方法,而且硬编码的代码也被移除了,难道5.0之后热点网关IP的配置又被更改了?继续跟踪文件diff发现有一次提交提到AP:

https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/d4f347f7de30834317dd1561dc806eccb1c4f277

这次提交说明有关于AP热点配置在WiFiStateMachine.java中的代码被迁移到SoftAPManager,然后通过SoftAPManager来集成,同时也提到了AP这块代码放在WiFiStateMachine代码不够清晰。

  • 继续挣扎

既然知道了代码迁移过程,那就需要跟着去寻找SoftAPManager。这个文件和WiFiStateMachine.java在同一包下,打开文件一看还是没有发现对于IP地址的硬编码部分,只能再次寻求log,这个文件的修改历史记录比较少,其中最老的一条对应于上文提到的AP状态管理通过SoftAPManager。通过历史查看这次修改发现了从WiFiStateMachine.java迁移过来的硬编码IP地址的代码。既然在创建时代码还存在,那么次新一条的历史记录就更加让人着迷了:

时隔上次迁移到SoftAPManager.java的三个月后,这块逻辑又要被搬家了,归宿就是Tether模块,这么一波三折到底是Android源码,修改的简直是猝不及防。

  • 上岸

上面提交记录中,提到的Tethering&TetherInterfaceStateMachine在platform/frameworks/base/services/core/java/com/android/server/connectivity/下面,关于硬编码的部分被迁移到TetherInterfaceStateMachine.java

硬编码IP的方式并没有改变,至此终于将代码的变化追踪完了,结果还是一套硬编码方式。当然乐在于真正找到了答案。