bat365手机版app-bt365官网哪个真的-365官方平台

【教程】Android(AOSP)Framework开发/ROM定制快速教程

【教程】Android(AOSP)Framework开发/ROM定制快速教程

【教程】Android(AOSP)Framework开发/ROM定制快速教程

备注一、基础知识二、基本操作1.源码获取2.编译刷机3.构建系统

三、系统结构1.系统架构2.目录结构3.源码结构

四、二次开发1.添加产品2.添加程序3.添加其他

五、启动流程1.BootROM阶段2.Bootloader阶段3.Kernel阶段4.init阶段5.Zygote阶段6.system_server阶段7.Launcher阶段

六、Binder1.原理2.组成3.流程4.AIDL

七、核心服务1.AMS2.PMS3.WMS

八、其他特性1.应用权限2.文件权限3.SELinux权限4.签名5.属性6.HAL

备注

2025/03/13 星期四 记录一下完整的Android系统开发知识,方便自己查阅

一、基础知识

Android是Google基于Linux内核研发的移动操作系统,Google将Android源码进行了开源称为AOSP(Android Open Source Project)。Android经过多年发展,除了手机还广泛应用于手表、平板、电视、车机等智能设备中。对AOSP源码做二次开发的工作一般称为Framework开发或者ROM定制。

Android设备制造行业一个基本的分工是: 1.Google开发AOSP 2.芯片厂商根据芯片适配AOSP(如高通、展锐、联发科、全志) 3.主板厂商(有的芯片厂商也当主板厂商)设计电路板,增加其他配件,在芯片厂商源码基础上继续修改做适配 4.设备制造商对主板厂商的源码定制UI、增加功能、优化系统(如华为、小米、OPPO、VIVO) 芯片厂商和主板厂商一般被称为vendor,设备制造商一般被称为oem或odm

另外,与传统固件(BIOS/UEFI、BootROM、硬件控制程序)概念不同,Android领域的固件很多时候也指包含了系统镜像、Linux内核、SE/TEE、Bootloader、Recovery等软件的线刷包。而“系统”多指基于AOSP修改得到的操作系统。

二、基本操作

1.源码获取

Google建议在Ubuntu上进行开发,提供了Android Studio for Platform作为开发工具。获取AOSP源码的操作如下:

# 安装基本依赖

sudo apt-get install git-core gnupg flex bison build-essential zip curl zlib1g-dev libc6-dev-i386 x11proto-core-dev libx11-dev lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig

# 安装源码管理工具repo

sudo apt-get install repo

# 初始化仓库

repo init --partial-clone -b [分支] -u https://android.googlesource.com/platform/manifest

# 拉取源码

repo sync -c -j8

2.编译刷机

对源码进行编译的操作如下:

source build/envsetup.sh

lunch

make -j$(nproc)

(注:Android中的内核文件是预编译好的,如果想要修改内核需要拉取对应的内核代码,修改编译后将编译结果放到指定路径,再重新编译打包Android镜像。) 编译完成后进行刷机的操作如下:

adb reboot bootloader

fastboot flashall -w

顺便一提,刷机的方式有fastboot、recovery、EDL和ota应用,这里我们选的是fastboot俗称线刷,也可以自行选用其他方式进行刷机(recovery俗称卡刷,EDL是紧急下载模式用于救砖,最知名是高通的9008,其他芯片厂商也有类似的工具,ota应用最常见的就是手机设置中的系统更新)

3.构建系统

​ Android提供了两种构建方式,在Android 7.0之前使用基于make的构建系统,使用Android.mk文件描make述构建规则,在Android 7.0后引入了soong构建系统,使用Android.bp文件描述soong的构建规则。soong中采用了kati GNU Make克隆工具和ninja后端来加速对系统源码的构建,用于解决make在Android中构建缓慢、容易出错、无法扩展、难以测试等问题。虽然make构建系统已经逐步被soong构建系统取代,但是仍然可以使用。 Android.mk:

// 设置当前构建所在目录,通常作为一个Android.mk文件中的第一行

LOCAL_PATH := $(call my-dir)

// 清空所有的LOCAL_变量,避免模块之间的变量相互干扰。

include $(CLEAR_VARS)

// 定义模块名称,必须是唯一不重复的,构建系统会根据类型自动添加前缀后缀

LOCAL_MODULE := my-module

// 模块类型(可选项),如APPS、 EXECUTABLES、SHARED_LIBRARIES、ETC

LOCAL_MODULE_CLASS := EXECUTABLES

// 模块所需全部源文件

LOCAL_SRC_FILES := src/test.cpp

// C/C++搜索头文件的路径

LOCAL_C_INCLUDES := $(LOCAL_PATH)/include

// 模块依赖的库文件(静态库.a和动态库.so)

LOCAL_STATIC_LIBRARIES:= lib1

LOCAL_SHARED_LIBRARIES:= lib2

// 编译选项

LOCAL_CFLAGS := -Wall -Wextra

LOCAL_CPPFLAGS := -std=c++11

// 构建类型,如BUILD_EXECUTABLE、BUILD_SHARED_LIBRARY、BUILD_STATIC_LIBRARY、BUILD_PACKAGE、BUILD_JAVA_LIBRARY、BUILD_PREBUILT

include $(BUILD_XXX)

Android.bp:

// 构建类型,如cc_binary、cc_library_static、cc_library_shared、android_app、java_library、java_library_static、prebuilt_apk

cc_library_shared {

// 模块名,如果是库文件通常约定加上'lib'前缀

name: "libdemo",

// 源文件列表

srcs: [

"src/test.c",

],

// C/C++搜索头文件的路径

include_dirs: ["include"],

// 编译选项

cflags: ["-Wall", "-Wextra"],

cppflags: ["-std=c++11"],

// 模块依赖的库文件(静态库.a和动态库.so)

shared_libs: [

"liblog",

"libcutils",

],

// 控制哪些模块可以依赖此模块,如:["//visibility:public"]、["//visibility:private"]、["//path/to:other_module"]

visibility: ["//visibility:public"],

}

另外Android提供了androidmk工具用于将Android.mk文件转换为Android.bp文件

三、系统结构

1.系统架构

Android分为5层结构,从上到下依次是应用层、系统框架层、原生库和运行时层、HAL层、内核层 应用层:用户直接与之交互的部分,包括各种应用程序和系统界面 框架层:提供Java/Kotlin类接口 原生库:C/C++ 库,一般是用于实现核心系统功能高性能的原生库 运行时:ART和Dalvik的虚拟机,用于执行dex文件 HAL:标准硬件接口,使Android以统一的方式调用硬件的功能 Linux内核:Android定制后的Linux内核,提供最基本的CPU调度、内存管理、文件系统等功能

2.目录结构

目录作用/acctLinux内核管理进程的CPU、内存、IO等资源的信息/cache系统临时更新和缓存/cache/backup备份目录/cache/recoveryrecovery目录/config/data用户数据目录/data/anr系统异常记录/data/adbadb数据目录/data/app存放用户安装的第三方应用app文件/data/dalvik-cache存放优化后的字节码,用于应用快速启动/data/data所有应用包括系统应用和第三方应用的私有数据/data/media内部存储/sdcard或/storage/emulated/0的实际挂载点/data/miscwifi、蓝牙、vpn、adb密钥等数据/data/propertypersist属性/data/system存放系统核心配置,如应用列表、账户信息、设备策略、锁屏设置等/data/user多用户的环境下指向/data/data的符号链接,用于实现多用户数据隔离/dev/mnt挂载外接设备/oem设备制造商目录/proc进程实时信息/rootroot用户家目录/sbinroot用户的二进制bin/sdcard符号链接,指向data/media或/storage/emulated/0/storage挂载所有存储设备的根目录/sysLinux内核的文件系统,提供虚拟文件系统、内核对象、设备驱动、硬件属性等/systemAndroid系统的核心文件/system/app存放Android的系统应用app/system/bin存放系统的命令行工具二进制elf/system/etc系统主机名、ip地址映射等配置文件/system/lib存放系统的动态库so/system/framework系统框架的核心jar/system/media存放系统铃声、提示音、开机动画等多媒体文件/system/fonts存放系统的字体/system/priv-app系统特权应用app/system/usr存放用户键盘布局、共享、时区等配置文件/system/xbin存放额外的命令行工具二进制elf

3.源码结构

目录作用art该目录是在Android 5.0中新增加的,主要是实现Android RunTime(ART)的目录,它作为Android 4.4中的Dalvik虚拟机的替代,主要处理Java字节码执行bionicAndroid的C库,包含了很多标准的C库函数和头文件,还有一些Android特有的函数和头文件build该目录包含了编译Android源代码所需要的脚本,包括makefile文件和一些构建工具compatibilityAndroid设备的兼容性测试套件(CTS)和兼容性实现(Compatibility Implementation)ctsAndroid设备兼容性测试套件(CTS),主要用来测试设备是否符合Android标准dalvikDalvik虚拟机,它是Android 2.3版本之前的主要虚拟机,它主要处理Java字节码执行developersAndroid开发者文档和样例代码development调试工具,如systrace、monkey、ddms等device特定的Android设备的驱动程序external第三方库,如WebKit、OpenGL等frameworksAndroid应用程序调用底层服务的APIhardwareAndroid设备硬件驱动代码,如摄像头驱动、蓝牙驱动等kernelAndroid系统内核的源代码,它是Android系统的核心部分libcoreAndroid底层库,它提供了一些基本的API,如文件系统操作、网络操作等packagesAndroid系统中的系统应用程序的源码,例如短信、电话、浏览器、相机等pdkAndroid平台开发套件,它包含了一些工具和API,以便开发者快速开发Android应用程序platform_testing测试工具,用于测试Android平台的稳定性和性能prebuilts预先编译的文件,如编译工具、驱动程序等sdkAndroid SDK的源代码,Android SDK的API文档、代码示例、工具等systemAndroid系统的核心部分,如系统服务、应用程序、内存管理机制、文件系统、网络协议等test测试代码,用于测试Android系统的各个组件toolchain编译器和工具链,如GCC、Clang等,用于编译Android源代码tools开发工具,如Android SDK工具、Android Studio、Eclipse等vendor硬件厂商提供的驱动程序,如摄像头驱动、蓝牙驱动等

四、二次开发

首先了解一下不同分区的作用,这里优先区分一下system、vendor、odm和product分区,

分区作用systemAOSP系统组件,所有product都通用的软件vendor芯片和主板厂商针对硬件开发的通用的可执行文件、库、系统服务和 app (不包含驱动)odm产品硬件差异导致的相关软件差异部分都会放在odm分区product软件差异都放在product分区

因此可以从软硬件、通用和差异方面简单理解为:

软件硬件通用systemvendor差异productodm

编译后的文件位置和编译命令如下:

分区Android.mkAndroid.bpsystem默认就是输出到 system 分区默认就是输出到 system 分区vendorLOCAL_VENDOR_MODULE := truevendor: trueodmLOCAL_ODM_MODULE := truedevice_specific: trueproductLOCAL_PRODUCT_MODULE := trueproduct_specific: true

1.添加产品

不同产品的源码会存在差异,通过配置文件来实现区分,这些配置文件称为 Product,每一个 Product 适用于特定的硬件产品,在编译时通过lunch进行选择。 Google提供的product 配置文件会保存在build/target目录下,芯片厂商或主板厂商提供的product配置文件在device目录下。 当我们想要添加自己的product 配置文件时一般也会选择在device目录下新增<公司名>/,再添加AndroidProducts.mk、.mk、BoardConfig.mk,可以参考AOSP原生文件进行编写。 AndroidProducts.mk是由构建系统自动扫描的入口文件,基本内容如下:

PRODUCT_MAKEFILES := \

$(LOCAL_DIR)/.mk \

COMMON_LUNCH_CHOICES := \

-user \

-userdebug \

-eng

.mk是产品的核心配置文件,用于定义产品的基础信息、引用其他配置文件、设置系统分区、预装程序、系统属性等,基本内容如下:

# 基本信息

PRODUCT_NAME :=

PRODUCT_DEVICE :=

PRODUCT_BRAND := <公司名>

PRODUCT_MODEL := <机型名>

# 引用其他配置

$(call inherit-product, )

# 构建类型

PRODUCT_BUILD_VARIANT := user

#是否使用自定义内核

TARGET_NO_KERNEL_OVERRIDE := true

# 分区配置

PRODUCT_SYSTEM_PROPERTIES += \

ro.system.size=4G

BOARD_SYSTEMIMAGE_PARTITION_SIZE := 4294967296

# 添加程序

PRODUCT_PACKAGES += \

\

\

# 添加属性

PRODUCT_PROPERTY_OVERRIDES := \

persist.sys.flag=1 \

ro.control.flag=0

# 添加文件

PRODUCT_COPY_FILES += \

$(LOCAL_PATH)/:$(TARGET_COPY_OUT_SYSTEM)/

BoardConfig.mk是定义硬件底层配置、芯片架构、分区大小、bootloader 和 kernel, 是否支持摄像头,GPS导航等一些板级特性的文件。

2.添加程序

Android中有很多bin目录,其中都是一些二进制可执行文件或shell脚本,这些程序源码主要来自于external、system/core、frameworks/native/cmds和frameworks/base/cmds,这里我们参考已有工具新建工具名目录、编写Android.bp文件、新建src/工具名目录并编写源码,在.mk文件中添加

PRODUCT_PACKAGES += 程序名

如果直接编译文件会被放到system分区,还需要在.mk文件中指定目标位置才不会报错

PRODUCT_ARTIFACT_PATH_REQUIREMENT_WHITELIST += \

system/bin/程序名\

system/app/程序名/程序名.apk \

system/lib/lib库名.so \

但是我们编写的工具大概率是产品相关的官方建议放到product分区下,Android.bp中添加product_specific: true即可

3.添加其他

类似的,还可以去添加库文件、配置文件、app等,方法大多差不多,只有一些细节差别,这里不过多赘述可以自行搜索

五、启动流程

Android系统启动可以分为七个阶段:BootROM阶段、Bootloader阶段、Kernel阶段、init阶段、zygote阶段、System Server阶段和Launcher阶段。

1.BootROM阶段

BootROM阶段在设备通电后,由SoC芯片内置只读程序初始化最基础的硬件(如CPU核心、时钟),查找并验签位于特定位置的Bootloader程序,如果验签通过则会加载Bootloader程序

2.Bootloader阶段

Bootloader一般分为两级,由BootROM加载的称为一级导加载程序(PBL),一级引导加载程序负责初始化更多基础硬件(如DRAM、eMMC/UFS、显示器),查找并验签位于特定分区的二级引导加载程序(SBL),如果验签通过则会加载二级引导加载程序。 二级引导加载程序继续初始化更多硬件,验签启动的镜像boot.img,如果验签通过则会加载boot.img到内存中。

3.Kernel阶段

Bootloader将boot.img 中的内核加载到内存中,CPU将控制权从Bootloader转交给内核,内核会初始化各类硬件设备、加载驱动程序、管理内存中断信号等。内核还会加载boot.img中一个最小临时文件系统initramfs,然后启动init进程

4.init阶段

init进程是Android系统中的第一个用户空间进程,PID为1。init进程又会读取init.rc文件,根据该文件中的配置信息加载正式的文件系统、启动并配置SELinux、启动Android系统的各个组件。init进程启动流程可以分为三个主要阶段:第一阶段初始化(first_stage_init)、SELinux设置(selinux_setup)二阶段初始化(second_stage_init)。第一阶段初始化主要是挂载分区,SELinux设置阶段会初始化SELinux相关的内容,第二阶段初始化完成进程和服务的启动。 init进程刚开始运行的时候是内核态,然后运行一个用户态程序把自己强行转成用户态,后面的操作全在用户态下进行,当init进程从内核态跳到用户态后,用户态下的程序无法再回到内核态,想要进入内核态只能通过系统调用。 init.rc文件是一个专门用于Android inti的配置文件,有三类语句:On、Service、Import。On是在Action的情况下执行Command,Service是定义服务的名称、路径、启动参数和配置项,Import是引入其他rc文件:

import /init.environ.rc

on

...

service [ ]

...

5.Zygote阶段

Zygote是由init启动的进程,Zygote负责预加载核心资源(framework.jar, framework-res.apk 等)、 ​​初始化 Android Runtime(ART),启动 system_server(com.android.server.SystemServer)。

6.system_server阶段

system_server是Zygote fork出来的第一个进程,负责启动和管理几乎所有关键native和java服务(如AMS、PMS、WMS、LocationManagerService、TelephonyManagerService、Wi-FiService、BluetoothService等),system_server启动完成后会通过广播所有已启动的服务。

7.Launcher阶段

AMS收到system_server发送的启动完成广播后会启动 Launcher​,Android系统就完全启动了,用户可以进入桌面使用各种应用程序。

六、Binder

1.原理

Binder是Android为了代替Linux IPC设计的,是具有远程过程调用RPC(Remote Procedure Call)能力的进程间通信IPC(Inter-Process Communication)机制。为了保证不同进程之间互不干扰,Linux为每个进程都分配有独立的虚拟内存空间,不同进程之间的用户空间相互独立实现进程隔离,系统上的所有进程共用一个内核空间,如果进程间想要相互访问数据就需要借助内核空间来实现。将数据从一个进程的用户空间复制到内核空间,再从内核空间将数据复制到另一个进程的用户空间,就可以达到跨进程访问数据的目的。但是需要做两次复制操作,如果将一个进程用户空间虚拟地址直接映射到内核空间的物理地址,再让另一个进程从内核空间复制数据,就可以优化为一次复制操作,这就是Binder的一次复制原理。 同时Binder提供了RPC能力。RPC就是像调用本地函数一样调用远程函数(远程包括逻辑和隔离和物理隔离,即本机其他进程或者网络上其他机器的进程),因此需要将数据按照一定的规则打包并发送给目标进程,目标进程解析数据执行函数后再将结果按一定格式发回给调用者。 Android中常见的IPC机制如Intent、Messenger、ContentProvider、AIDL底层都是由Binder实现的。

2.组成

Android的Binder主要包括了Client、Server、ServiceManager和Binder驱动四个部分。 Client是发起调用的进程 Server是提供Service的进程,Service是被调用的函数集合 ServiceManager是用于管理Service的进程,Server需要将Service注册到ServiceManager才能被Client调用 Binder驱动是内核层的特殊​​字符设备驱动​​,用于实现IPC需要具有访问内核空间的能力,但是Android并不属于Linux内核,不能直接访问内核空间,因此使用Linux的动态可加载内核模块(Loadable Kernel Module,LKM)的机制,将Binder驱动单独编译后再链接到内核中。

3.流程

Binder的核心流程包括:系统启动ServiceManager、Server注册Service、Client调用Service

4.AIDL

由上文可见使用binder需要涉及到内核驱动、naive层、java层非常复杂,Android提供了AIDL用于简化binder使用

七、核心服务

1.AMS

2.PMS

3.WMS

八、其他特性

1.应用权限

2.文件权限

3.SELinux权限

4.签名

5.属性

6.HAL

相关推荐