AOSP总结

AOSP

看分析文章,看源码,调试源码,自己实现,是四个完全不同的层级,每一级对源码的理解都不一样
Android Open Source Project

引用:

Android Framework
https://github.com/yuandaimaahao/AndroidFrameworkTutorial
使用 Android Studio 开发系统 App
系统开发专用版 Android Studio 上手指南 - 掘金

编译源码

命令

下载AOSP源码编译、调试、刷机
Ubuntu 20.04 添加新的Swap分区 - 掘金

下载源码

1
2
3
4
5
6
7
8
9
git config --global user.email "" 
git config --global user.name ""

mkdir aosp11
cd aosp11
#初始化仓库,-b 指示分支,这里使用 android10
repo init -u https://mirrors.tuna.tsinghua.edu.cn/git/AOSP/platform/manifest -b android-11.0.0_r4
#同步远程代码
repo sync

编译源码

1
2
3
4
source build/envsetup.sh
lunch aosp_x86_64-eng
make -j1 12 m
make clean

源码文件目录结构

【视频文稿】车载Android应用开发与分析 - AOSP的下载与编译 - 掘金

  • package
    应用层(Application)源码。系统应用就在这里了,比如说系统设置,桌面,相机,电话之类的。
  • frameworks
    系统框架(Framework)层源码。
  • hardware
    硬件抽象(HAL)层源码。
  • out
    输出目录。编译以后生成的目录,相关的产出就在这里了
    在 Android 的源代码编译系统中,out/soong 通常是一个存放编译过程中生成的临时文件和最终构建产物的目录
  • build
    用于构建 Android 系统的工具。也就是用于编译 Android 系统的

遇到的问题

同步用python 3.8,编译用2.7
切换Python配置

1
sudo update-alternatives --config python

如果可能,尝试清理构建环境并重新编译(例如运行 make clean 或者直接删除整个 out/soong/.intermediates/ 目录后再次编译)。

AOSP编译问题

ubuntu16.04 编译Android AOSP源码 android10

Android.bp

Android.bp 文件是用于构建 Android 系统或 Android 应用的构建描述文件。它是在 Android Open Source Project (AOSP) 中引入的一种构建系统脚本语言,取代了旧版本的 Makefile,一种新的编译文件

Android.bp 文件用于定义项目的模块、依赖关系、编译选项以及其他构建规则。通过编写 Android.bp 文件,可以指定项目的源代码文件、资源文件、库依赖关系、编译选项等信息,以及生成最终构建产物(例如 APK 文件)所需的各个步骤和过程。

使用 Android.bp 文件进行构建有以下优势:

可读性好:相比于 Makefile,Android.bp 文件更易于阅读和理解,使构建配置更加清晰明了。
扩展性强:Android.bp 提供了丰富的构建规则和函数,可以方便地扩展和定制构建流程。
并行构建:Android.bp 支持并行构建,提高构建效率。
需要注意的是,Android.bp 文件通常与 Soong 构建系统配合使用。Soong 是 Android 中的新构建系统,用于替代旧的 Make 构建系统。Android.bp 文件是 Soong 构建系统的配置文件之一,用于描述单个模块的构建规则。

unknown_filename

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
android_app {
    name: "FirstSystemApp",
    srcs: ["src/**/*.java"],
    resource_dirs: ["res"],
    manifest: "AndroidManifest.xml",
    platform_apis: true,

    sdk_version: "",
    certificate: "platform",
    product_specific: true,
    //依赖
    static_libs: ["androidx.appcompat_appcompat",
                "com.google.android.material_material",
                "androidx-constraintlayout_constraintlayout"],
}

AIDEGen

AIDEGen,我叫它 “爱得跟”,大概是 Android10 中,google 推出的一个工具,用于方便开发者使用 IDE 来查看和修改系统源码,使用 “爱得跟” 之前我们需要做一些准备工作,编译 sdk:

1
2
3
4
5
6
7
source build/envsetup.sh
lunch sdk-eng
# or
#lunch sdk-userdebug
# or
#lunch sdk-user
make sdk

接着我们需要去 google 官方下载 Android Studio,这里推荐3.6.3版本,并将其放到 /opt 目录下。

接下来,选择我们的目标 Product:

1
2
source build/envsetup.sh
lunch aosp_x86_64-eng

做好以上准备工作后,我们就可以打开系统模块了,这里我们以 Settings 为例:

1
2
3
4
# Settings 更换为其他模块名或是模块存在的路径即可打开其他模块
aidegen Settings -i s # -i 表示使用ide,s 表示 Android Studio

aidegen Launcher3 -i s

settings的路径:aosp/packages/app/Settings

模拟器

1
2
emulator -verbose    查看日志
emulator -verbose -cores 4 -show-kernel

unknown_filename
https://www.cnblogs.com/chiefhsing/p/5175624.html

mm和mmm的主要区别

在Android源码编译中,mm和mmm的主要区别在于它们编译的范围。

  1. mm:这个命令用于在当前目录下编译模块。所谓模块,就是一个可执行文件、库或者APK等。比如你正在某个应用的目录下(例如packages/apps/Calculator),执行mm将会只编译这个计算器应用。
  2. mmm:这个命令与mm类似,但是它允许你指定一个路径来编译模块。例如,在源代码根目录下执行mmm packages/apps/Calculator将会只编译计算器应用。
    总结一下,如果你已经处在需要编译的模块目录下,则使用mm;如果你不在需要编译的模块目录下,则使用mmm并指定相对应的路径。

mm和mma

在Android源码编译中,mmamm命令都是用于编译模块的,但它们之间存在一些区别:

  1. mm: 这个命令只会编译当前目录下的模块,并且不包括依赖项。这意味着如果你正在尝试编译一个模块,而这个模块依赖于另一个尚未编译的模块,则该命令可能会失败。因此,使用 mm 前需要确保所有依赖项都已经被正确地构建了。
  2. mma: 这个命令将会编译当前目录下的模块以及其所有依赖项。也就是说,如果你正在尝试构建一个有很多依赖项的大型项目或者库文件,那么使用 mma 可能更为方便。

总结来说, mm 是单独对某一组件进行增量式构建, 不考虑其相关联组件;而 mma 则会考虑到相关联组件进行增量式构建

编译某个单独的模块

如果我们要编译系统的Settings应用模块,这就属于源码单编某一个模块,在AOSP根目录执行:

1
2
source build/envsetup.sh
lunch aosp_x86_64-eng

进入Settings的目录:

1
cd packages/apps/Settings

通过mm编译当前目录下的模块,不编译依赖模块。

编译成功后会有提示生成文件的存放路径。除了Settings.odex文件,还会在out/target/product/generic_x86/system/priv-app/Settings目录下生成Settings.apk。

如果对系统模块的源码进行修改,查看生成的APK文件,有两种方式:

  • 通过adb push或者adb install 来安装APK。
  • 使用make snod命令,重新生成 system.img,运行模拟器查看。

熟悉模块

熟悉Android framework中一个或数个功能模块框架,如GPS、WiFi、BT,Camera,音视频编解码,Telephony ,系统应用(Settings,SystemUl, Launcher) 等

Launcher3-dev/Launcher3: 来源 AOSP Launcher3 源码,单层桌面请查看Launcher-mx项目:
[[8-Launcher学习]]

调试系统App Settings

首先,我们开一个新的终端,打开模拟器:

1
2
3
source build/envsetup.sh
lunch aosp_x86_64-eng
emulator
  • 接着我们在 Settings/AndroidManifest.xml 查找到 Settings App 的首 Activity 为 SettingsHomepageActivity,我们在其 onCreate 出打一个断点
  • 接着在 Android 模拟器中打开 Settings 应用。
  • 点击 android studio 的 debug 按钮,选择进程,和普通APP一样

添加 Product

Android 的系统源码,经过简单的配置,可以打包出不同的系统镜像,用于不同的产品。例如小米 12s,小米12s pro,小米12s ultra 均源于骁龙8+平台。
image.png

添加自己的product

1
2
3
4
5
Jelly/
└── Rice14
├── AndroidProducts.mk
├── BoardConfig.mk
└── Rice14.mk

BoardConfig.mk 包含了硬件芯片架构配置,分区大小配置等信息

Rice14.mk 修改最后4行

1
2
3
4
5
# Overrides
PRODUCT_BRAND := Jelly
PRODUCT_NAME := Rice14
PRODUCT_DEVICE := Rice14
PRODUCT_MODEL := Android SDK built for x86_64 Rice14

AndroidProducts.mk 内容如下:

1
2
3
4
5
6
7
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/Rice14.mk

COMMON_LUNCH_CHOICES := \
Rice14-eng \
Rice14-userdebug \
Rice14-user \

最后

1
2
3
4
source build/envsetup.sh
lunch Rice14-eng
make -j16
emulator

ARM + Android 行业流程与 Android 分区

ARM + Android 这个行业,一个简化的普遍流程:

  1. Google 开发迭代 AOSP + Kernel
  2. 芯片厂商,针对自己的芯片特点,移植 AOSP 和 Kernel,使其可以在自己的芯片上跑起来。
  3. 方案厂商(很多芯片厂商也扮演了方案厂商的角色),设计电路板,给芯片添加外设,在芯片厂商源码基础上开发外设相关软件,主要是驱动和 hal,改进性能和稳定性。
  4. 产品厂商,主要是系统软件开发,UI 定制以及硬件上的定制(添加自己的外设),改进性能和稳定性.

不同产品之间公共的部分放在 System 和 Vender 分区,差异的部分放在 Odm 和 Product 分区
硬件上,产品 A 可能用的是京东方的屏,产品 B 可能用的是三星的屏;差异硬件相关的软件部分都会放在 Odm 分区
产品 A 可能是带广告的版本,产品 B 可能是不带广告的版本。这些有差异的软件部分都放在 Product 分区

删除已有模块

有的时候,我们需要删除系统中已有的模块,比如我们系统的应用场景是广告牌、电视,那我们就需要删除电话,通信录等应用。下面以删除通信录(Contacts)为例,演示如何操作:

在源码的 build 目录下,先查找
grep -r “Contacts” .

1
2
3
4
./make/target/product/handheld_product.mk:    Contacts \
./make/target/product/mainline_arm64.mk: system/priv-app/Contacts/Contacts.apk \
./make/target/product/base_system.mk: ContactsProvider \
./make/core/build-system.html:Dialer, Contacts, etc. This will probably change or go away when we switch

在源码的 build 目录下的 ./make/target/product/handheld_product.mk 中删除 PRODUCT_PACKAGES 变量的 Contacts

接着重新编译启动模拟器:

1
2
3
4
5
source build/envsetup.sh
lunch Rice14-eng
make clean
make -j16
emulator

可以看到,Contacts 应用已经没有了

新建一个系统 App 项目

image.png

  1. 创建as项目
  2. 修改已添加的 Android.bp 文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    android_app {
    name: "FirstSystemApp",

    srcs: ["src/**/*.java"],

    resource_dirs: ["res"],

    manifest: "AndroidManifest.xml",

    platform_apis: true,

    sdk_version: "",

    certificate: "platform",

    product_specific: true,

    //依赖
    static_libs: ["androidx.appcompat_appcompat",
    "com.google.android.material_material",
    "androidx-constraintlayout_constraintlayout"],

    }
  3. 接着在我们的 Product 中添加这个App,修改 device/Jelly/Rice14/Rice14.mk
1
2
# 添加以下内容
PRODUCT_PACKAGES += FirstSystemApp
  1. 接着编译系统,启动虚拟机,打开 app

当我们的系统 App 需要引入一个库的时候,通常会在 prebuilds 目录下查找:

  • androidx 相关库引入,先在 prebuilts/sdk/current/androidx 下寻找配置好的 bp 文件
  • 其他库引入,先在 prebuilts/tools/common/m2 下寻找寻找配置好的 bp 文件

以 aar 包形式引入

1
2
3
liblottie/
├── Android.bp
└── lottie-5.2.0.aar

其中 Android.bp 的内容如下:

1
2
3
4
5
android_library_import {
name: "lib-lottie",
aars: ["lottie-5.2.0.aar"],
sdk_version: "current",
}

static_libs :添加依赖库
然后我们修改 FirstSystemApp 中的 Android.bp 引入这个库:

1
2
3
4
5
static_libs: ["androidx.appcompat_appcompat",
"com.google.android.material_material",
"androidx-constraintlayout_constraintlayout",
"FirstSystemAndroidLibrary",
"lib-lottie"],

这样就可以在 App 中使用 lottie 库了

系统 App 与 普通 App 的差异

系统 App 可以使用更多的 api

调用 Hide 的 Api
当 platform_apis 为 true 时,sdk_version 必须为空。这种情况下我们的 app 会使用平台 API 进行编译而不是 SDK,这样我们的 App 就能访问到非 SDK API 了

系统 App 的签名

AOSP 内置了 apk 签名文件,我们可以在 Android.bp 中通过 certificate 配置系统 app 的签名文件

系统 App 能使用更多的权限

系统 App 能更轻松地实现进程保活

三方 App 为了不被杀掉,可以说是用尽了千方百计。保活对于系统 App 其实是非常简单的:

在 AndroidManifest.xml 中添加如下参数即可:

1
2
<application
android:persistent="true">

系统 App 添加依赖

在 Android.bp 中引入:

1
2
3
4
5
6
7
8
9
10
11
12
android_library_import {
name: "androidx.recyclerview_recyclerview-nodeps",
aars: ["m2repository/androidx/recyclerview/recyclerview/1.1.0-alpha07/recyclerview-1.1.0-alpha07.aar"],
sdk_version: "current",
min_sdk_version: "14",
static_libs: [
"androidx.annotation_annotation",
"androidx.collection_collection",
"androidx.core_core",
"androidx.customview_customview",
],
}

其他概念

Android里AIDEGen和Idegen

Idegen 编译成android.ipr 和 android.iml 方便查看源码
AIDEGen 方便开发者使用 IDE 来查看和修改系统源码。

aidegen介绍
[[Android 系统开发工具推荐#^3b8a5e| 如何编译aidegen]]
aidegen是AOSP中自带的一个工具,可以将源码中的某个工程导入进IDE,从而可以使用IDE的智能提示,提高编码效率。而源码中的工程并不是独立存在的,还会依赖其他工程中的各种模块,aidegen 会主动把对应的模块编译一遍,同时把这些依赖都整理好导入到IDE中,从而避免因为找不到依赖而爆红的问题。

mk文件

在软件开发中,.mk 文件通常是用于构建(build)和编译(compile)代码的 Makefile 文件的扩展名。Makefile 是一种脚本文件,其中包含了一系列构建和编译源代码的规则、命令和依赖关系。

Makefile 文件使用 Make 工具来根据规则中定义的依赖关系和命令来自动化代码构建过程。Make 工具会解析 Makefile 文件,并根据需要执行相应的构建命令,以确保源代码正确地编译成可执行文件、库文件或其他所需的目标。

在 .mk 文件中,您可以定义变量、规则(例如编译规则、链接规则等)和其他构建相关的配置。这些文件通常由开发人员根据项目的需要进行编写和维护。

fastboot

Android fastboot 是一种用于在 Android 设备上执行各种操作的命令行工具。它是 Android 平台上的一个工具集之一,通常与 Android SDK(软件开发工具包)一起使用。

Fastboot 提供了一种与设备进行通信并执行一系列操作的方式,包括但不限于以下内容:

刷写固件:通过 fastboot 命令,您可以将新的固件(如操作系统、引导程序等)刷写到 Android 设备中,从而更新或修改设备的软件。

进入 bootloader 模式:通过 fastboot 命令,您可以将 Android 设备设置为 bootloader 模式,这是设备的引导程序。在 bootloader 模式下,您可以执行诸如刷写固件、解锁引导加载程序等操作。

解锁引导加载程序:某些 Android 设备的引导加载程序(bootloader)可能被锁定,以防止未经授权的固件刷写。fastboot 命令可以用于解锁引导加载程序,以便您可以自由刷写或修改设备的固件。

查看设备状态:fastboot 命令可以用于获取有关设备的信息,例如设备序列号、产品型号、固件版本等。

请注意,使用 fastboot 命令需要在计算机上安装 Android SDK,并在 USB 调试模式下连接支持 fastboot 的 Android 设备。

使用 fastboot 命令需要谨慎操作,因为错误的使用可能导致设备出现问题或数据丢失。在使用 fastboot 前,请确保您对操作有足够的了解或按照官方文档和指南进行操作。

HIDL

HIDL,全称为Hardware Interface Definition Language(硬件接口定义语言),是Android 8.0引入的一种新的硬件抽象层(HAL)框架。

在以往的Android系统版本中,HAL是通过C语言实现的,并且通常与特定版本的Android系统紧密耦合。这就意味着当Android系统升级时,相关的硬件驱动也需要更新以适配新版系统。


AOSP总结
http://peiniwan.github.io/2024/04/c734e9ba03ba.html
作者
六月的雨
发布于
2024年4月6日
许可协议