title: android框架笔记
comments: true
toc: true
date: 2018-03-15 09:02:05
tags:
- android
- framework
[TOC]
《Android框架揭秘》笔记。
Android框架概要
源代码结构
- kernel – 内核
- bionic – 标准C运行支持库
- bootloader – 内核加载器参考
- build – build系统
- cts – 兼容性测试源
- dalvik – 虚拟机
- art – 虚拟机
- external – 开放源
- frameworks – 框架
- hardware – HAL库源
- packages – Android基本应用
- system – 初始化进程、蓝牙工具集
通过启动过程分析framework
- bootloader加载Linux内核
- init进程
- 运行Daemon(C/C++程序)
- USB(usbd)
- ADB(adbd)
- Debugger(debugged)
- Radio Interface Layer(rild)
- 运行Context Manager(C/C++程序)
- 运行Media Server(C/C++程序)
- 运行Zygote(Java程序)
- 运行Daemon(C/C++程序)
Context Manager
管理Android系统服务的重要进程,提供Android内的各种系统服务信息。
系统启动时,Android所有系统服务要把各自的handle信息注册到Context Manager,Binder IPC用于进程间通信。Media Server – 本地服务注册
运行基于C/C++的本地系统服务,如Audio Flinger,Camera等Zygote
- 运行System Server
- System Server – Java服务注册
- 创建Power Manager Service
- 创建Sensor Service
- 创建Location Service
- 创建Connectivity Service
- 创建Activity Manager Service
- 运行HOME应用
源代码级别调试
导入源代码到AS
依赖源代码工程
断点调试HelloWorld程序
init进程
在用户空间启动init进程,再依次启动系统运行所需其他进程,系统启动完成后,init进程作为守护进程监视其他进程,监视中的进程终止时释放进程所占用的系统资源。
运行过程
init是内核启动的第一个用户级进程。
启动过程
- start_kernel()
- init_post()
- run_init_process() – 运行init进程。
源码分析
分析及运行init.rc文件
代码位置:/android/system/core/init/init.cpp
- 分析init.rc文件
- 分析/system/etc/init、/vendor/etc/init、/odm/etc/init文件
- 执行early-init动作列表 – ActionManager.QueueEventTrigger()
- 执行init动作列表 – ActionManager.QueueBuiltinAction()
- 执行bootmode动作列表
- 运行服务列表
生成设备驱动节点
代码位置:/android/system/core/init/init.cpp
- 生成并装载目录
- tmpfs(虚拟内存的文件系统) – /dev
- devpts(虚拟终端文件系统) – /dev/pts
- sysfs(特殊的文件系统) – /sys
- proc(虚拟的文件系统) – /proc
- selinuxfs(虚拟的文件系统) – /sys/fs/selinux(se: security enhanced)
初化内核记录器,重定向stdin/stdout/stderr到/dev/null。
Unix类系统中,所有输入输出被视为文件,标准输入为0,标准输出为1,标准错误输出为2。
- 生成设备静态节点 – SetInitAvbVersionInRecovery()
- 初始化SELinux – selinux_initialize()
- 注册POLL事件
处理子进程终止
详细代码位置:/android/system/core/init/signal_handler.cpp
- 注册SIGCHLD信号handler – signal_handler_init();
- 生成UDS(Unix Domain Sockets)套接字
- 注册POLL事件
属性服务
- 属性初始化 – property_init()
- 属性初始化设置 – property_set属性更改只能在init进程中执行
- 运行属性服务 – start_property_service();
- 注册POLL事件
init.rc脚本文件分析与执行
init.rc用来设置系统环境,记录待执行的进程。
init.rc脚本使用AIL(Android Init Language)编写。
AIL语言详细介绍:/android/system/core/init/README.md。
文件结构
文件以行为单位,用空格分隔标识符,#号标示注释。使用C语言格式的反斜杠转义字符插入空白,双引号用来避免空白符分隔标识符。末尾的反斜杠表示折行。
动作和服务隐式声明新区域,所有的命令或配置属于最近声明的区域,区域开始前的命令或配置将被忽略。
动作和服务要求唯一性,动作以最先声明的为准,重复声明的服务将被忽略并无性繁殖错误日志。
- actions – 动作,以on开头
拥有触发器来决定何时执行命令。
on {trigger} [&& {trigger}]*
{command}
{command}
- service – 服务
init进程启动的服务,配置服务退出时是否需要重启。
service {servicename} {servicepath} [{argument}]*
{option}
{option}
option – 配置
配置基于服务的,描述init进程何时如何运行服务。- console – 服务需要控制台,默认值为default。
- critical – 设备关键性服务,在四分钟内退出超过四次,设备将重启进入恢复模式
- disabled – 服务不会自行启动
- setenv – 设置环境变量
- socket – 创建UDS套接字,传递fd到启动进程。
trigger – 动作触发器
匹配指定事件类型的字符串,用来触发相应动作。
触发器可分为事件触发器(触发命令)和属性触发器(属性键值对)。
动作可以有多个属性触发器,但只能有一个事件触发器。
// 仅启动事件触发,且属性a等于b时触发动作。
on boot && property:a=b
// 可触发三次:初始启动时,a=b且c=d时触发;a=b,当c变为d时触发;c=d,当a变为b时触发。
on property:a=b && property:c=d
command – 命令
- bootchart
- chmod
- chown
- class_start/stop
import – 导入其他rc配置文件
- properties – 属性项,用于属性触发器
- boot timing
- ro.boottime.init
- ro.boottime.init.selinux
- boot timing
init.rc文件分析函数
使用了Parser类分析init.rc脚本。
Parser类路径:/android/system/core/init/init_parser.cpp
- AddSectionParser – 添加相应区域解析器
- ParseConfig – 执行解析
- ParseConfigDir
- ParseConfigFile
- read_file() – 读取文件到内存,返回字符串初始地址
- ParseData – 解析数据
- next_token – 返回
- ParseData – 解析数据
- read_file() – 读取文件到内存,返回字符串初始地址
动作列表与服务列表的运行
ActionManager和ServiceManager
yaffs2(yet another Flash file system)
- /
- var
- tmp
- system
- bin – shell命令
- app – 系统应用
- framework – java库
- lib – bionic 标准C库
- usr/fonts/media/etc/sounds/lost+found
- proc
- sys
- sbin
- etc
- data
- system/dalvik/cache/drm/logs/download/data/app/…
- root
创建设备节点文件
udev – 用户空间设备,守护进程,获取主、次设备号等信息,供mknod命令创建设备节点,避免主次设备号发生重叠。
冷拔插
预先定义设备信息,init进程启动时统一创建设备节点文件。
系统启动完成前udev守护进程未运行。init进程按预定义的设备信息创建设备节点文件。udev的职责由init进程完成。
热拔插
系统运行过程中,有设备插入USB端口,init进程接收设备插入事件,动态创建设备节点文件。
系统运行中设备插入,内核加载设备相关驱动程序,驱动程序调用启动函数probe(),将主次设备号、设备类型保存到/sys文件系统中,然后发出uevent(用户空间事件-内核向用户空间进程传递信息的信号系统),传递给udev守护进程,udev比较uevent与/sys中的设备信息,通过后在/dev目录创建设备节点文件。
进程的终止与再启动
init的子进程意外终止时,会产生SIGCHLD传递给init进程,init接收进程后检查进程选项是否为oneshot,若是,放弃重启,否则重启进程。
大部分init启动的进程意外终止时,需要重启。
init启动的主要进程有:
- sh – shell程序
- adbd – ADB守护进程
- servicemanager – 服务管理器
- vold(Volume Dameon) – 挂载/管理USB存储或SD卡设备
- playmp3 – 输出启动声音
属性服务
系统提供ashmen(Android Shared Memory)区域存储系统运行时所需的属性值,供所有进程共享。
属性区域由1024字节的属性域头和247块128字节的属性块组成。
属性块由32字节的name、4字节的系列号和92字节的值构成。
只有init进程才能修改属性值。因此其他进程需要修改属性,大概流程为:
- 向init进程发出请求
- init进程检查访问权限
- init进程修改属性值
- 满足条件的属性触发器被触发
JNI与NDK
安卓与JNI
使用JNI的场景:
- 注重处理速度
- 硬件控制
- 复用C/C++代码
注册JNI本地函数
调用SystemloadLibrary()方法时,Java虚拟机会加载其参数指定的共享库,然后Java虚拟机检索共享库内的函数符号,检查JNI_OnLoad()函数是否实现,若实现则JNI_OnLoad()函数被自动调用,否则Java虚拟机将自动匹配本地方法和库内JNI本地函数符号。
手动映射本地方法与JNI本地函数时,需在JNI_OnLoad()函数内调用RegisterNatives()函数进行映射匹配。
Zygote
简介
Zygote通过COW(Copy on Write)方式对运行在内存中的进程实现最大程序的复用,通过库共享降低内存的使用量。
Zygote启动后,初始并运行Dalvik虚拟机,预加载需要的类和资源到内存。启动应用程序时,fork()创建出Zygote子进程,Zygote子进程动态加载并运行应用程序。
COW – 针对内存复制的一种技术。复制内存的开销非常大,创建子进程在引用父进程的内存空间时,先不复制,直接共享父进程的内存空间。当需要修改共享内存中的信息时,子进程才将父进程中相关的内存信息复制到自身的内存空间,再进行修改。
由app_process运行ZygoteInit class
Zygote由Java编写而成,不能由init进程启动运行,需先生成Dalvik虚拟机,再在Dalvik虚拟机上装载运行ZygoteInit类,这一类型任务由app_process进程完成。
- init进程启动app_process服务
- app_process进程创建Dalvik虚拟机
- 生成AppRuntime对象 – AndroidRuntime类
- 调用AppRuntime对象
- 生成Dalvik虚拟机
- Dalvik虚拟机初始化Zygote
- 调用ZygoteInit类
ZygoteInit类的功能
- 绑定套接字,接收新Android应用程序运行请求
- 加载Android Application Framework使用的类和资源
- 启动运行SystemServer
- startSystemServer
- init1 – 启动本地服务
- init2 – 启动Android framework主要服务
- startSystemServer
- 处理新Android应用程序请求
Android服务概要
服务的种类
- 系统服务 – Framework提供
- Java系统服务
- 核心平台服务
- 硬件服务
- 本地系统服务
- Java系统服务
- 应用程序服务 – 继承Service类
- 本地服务
- 远程服务
应用程序服务
后台服务程序,无UI界面,定期执行某些任务。
服务运行方式
- 服务启动与终止 – onStartCommand
- 服务绑定 – onBind/onUnbind
服务分类
本地
使用LocalBinder作为通信通道。
交互流程:
- activity.bindService()
- service.onBind() – LocalBinder子类
- activity.onServiceConnected()
- localBinder.getService() – Service对象
远程
由于应用程序在各自沙箱中运行,故需要通过IPC机制进行应用进程间通信。
用户定义AIDL,aidl工具自动生成实现类及内部类Stub,Stub.Proxy。
交互流程:
- activity.bindService()
- service.onBind() – IInteface.Stub.Proxy(AIDL的生成类)
- activity.onServiceConnected()
- IInteface.Stub.onTransact()
系统服务
本地系统服务
用C++编写,运行在Libraries层。
- Audio Flinger
- 耳机设备
- 话筒设备设备
- 蓝牙设备
- Surface Flinger
- Frame Buffer设备
Java系统服务
由SystemServer进程启动,分为核心平台服务与硬件服务。
核心平台服务
不直接与Android应用程序交互,android framework运行必须的服务。
- Activity Manager Service
- Window Manager Service – 将要绘制的内容传递给Surface Flinger
- Package Manager Service
硬件服务
用于控制底层硬件。
- Alarm Manager Service
- Connectivity Service
- Location Service
- Power Service
- Sensor Service
- Telephony Service
- Wifi Service
运行系统服务
系统服务由系统启动,使用时,直接调用getSystemService获取服务。
Media Server
负责启动除Surface Flinger外的本地服务。
功能:生成各服务的对象,并注册到Context Manager中。
System Server
负责启动Surface Flinger, Java系统服务。
- SystemServer.main加载android_servers库,并调用init1方法
- init1方法通过JNI调用system_init函数,初始化Surface Flinger,调用init2方法
- init2方法创建ServerThread对象并启动
- ServerThread创建Java系统服务,调用ServiceManager.addService方法注册服务到Context Manager。
Android Service Framework、Binder Driver概要
foo()方法调用流程:
- 服务客户端调用foo()代理方法
- RPC层生成Binder RPC数据(包含引用Foo服务的请求)
- Binder RPC数据经过Marshalling(编组)处理,由服务框架(Service Manager)生成Binder IPC数据
- Binder驱动传递Binder IPC数据给服务框架(Service Manager),unMarshalling(反编组)处理为Binder RPC数据
- Service Stub的onTransact方法处理Binder RPC数据,定位请求的RPC方法
- 使用Binder RPC数据调用foo()方法。
Android Binder IPC
Linux内存空间与Binder Driver
虚拟地址空间划分为用户空间和内核空间。
各进程拥有独立的用户空间,共享内核空间。
Binder提供IPC通信功能,支持进程间的RPC操作,使用运行在内核空间的抽象驱动程序Binder Driver。
Binder通过内核空间传递数据确保数据的可靠性,基于用户空间无法访问访问内核空间交换数据保证IPC的安全性。
Android Binder Model
Binder Driver接收来自服务客户端的Binder IPC数据,传递给服务端,从而实现进程间的通信。
IPC数据包含如下几个部分:
- handle – 服务号
- RPC代码 – 调用函数
- RPC数据 – 调用函数参数
- Binder协议 – IPC数据的处理方法
Binder IPC数据传递
Binder Driver是字符设备驱动程序。
系统调用:用户空间调用内核空间函数的接口。
应用程序通过Binder尝试RPC操作,系统调用流程:
- open() – 获取Binder Driver的文件描述符
- mmap() – 在内核中开辟一块区域
- ioctl() – 将IPC数据作为参数传递给Binder Driver
- BINDER_WRITE_READ – ioctl命令
Binder IPC抽象层
- 服务层 – 客户端调用代理函数,服务端调用函数
- RPC层 – 生成和分析RPC代码和数据
- IPC层 – 编组和反编组RPC代码和数据为Binder IPC数据
- Binder Driver层 – 传递IPC数据
Binder协议
BC_TRANSACTION(Binder Command) – IPC层传递给Binder Driver层
- 通过handle查找Service Server
- 更改协议为BR_TRANSACTION
- 向Service Server传递IPC数据
BR_TRANSACTION(Binder Return) – Binder Driver层传回给IPC层
- 分析IPC数据
- 调用与RPC代码相应的函数
Binder寻址
Context Manager为注册的每个服务分配一个称为Handle的服务号,并提供服务的添加、检索等管理功能,Context Manager自身的Handle值设置为0。
Binder寻址,指inder Driver根据IPC数据中的Handle查找Service Server这一过程。
Android Binder Driver分析
从进程角度看服务的使用
服务注册
Context Manager: 接收IPC数据,发送IPC应答数据
Service Server: 发送IPC数据,接收IPC应答数据
进程交互:
- Context Manager调用Binder Driver的open/mmap/ioctl函数等待IPC数据
- Service Server调用Binder Driver的open/mmap/ioctl函数发送IPC数据
- Context Manager接收IPC数据,完成服务注册,发送IPC应答数据
- Service Server接收IPC应答数据,Binder IPC完成
服务检索
Context Manager: 接收IPC数据,发送IPC应答数据
Service Client: 发送IPC数据,接收IPC应答数据
进程交互:
- Context Manager调用ioctl函数等待IPC数据
- Service Client调用Binder Driver的open/mmap/ioctl函数发送IPC数据
- Context Manager接收IPC数据,完成服务注册,发送IPC应答数据
- Service Client接收IPC应答数据,Binder IPC完成
服务使用
Service Server: 接收IPC数据,发送IPC应答数据
Service Client: 发送IPC数据,接收IPC应答数据
进程交互:
- Context Manager调用ioctl函数等待IPC数据
- Service Client调用Binder Driver的open/mmap/ioctl函数发送IPC数据
- Context Manager接收IPC数据,完成服务注册,发送IPC应答数据
- Service Client接收IPC应答数据,Binder IPC完成
从Binder Driver角度看服务的使用
服务注册
Context Manager先于Service Server运行,最先使用Binder Driver。
服务检索
客户端向Context Manager请求指定服务的Handle的过程。
服务使用
客户端向Service Manager发起RPC调用。
Context Manager
对应进程为servicemanager,先于Service server和Service client运行。
main()函数大致的三部分:
- binder_open() – 打开Binder Driver
- binder_become_context_manager() – 注册服务号handle = 0
- binder_loop() – 接收IPC数据
Android Service Framework
服务框架
安卓服务框架提供的主要功能:
- 服务接口 – AIDL
- 服务生成 – Stub, Stub.Proxy
- Binder IPC处理
- 服务管理 – 服务注册及检索
服务框架的构成
各层元素配置
- 服务层
- 客户端 – IFooService接口
- 服务端 – FooService和IFooService接口
- RPC层 – RPC转换与分析
- 客户端 – BpFooService代理服务
- 服务端 – BnFooService服务Stub
- IPC层 – IPC传输,与RPC转换与分析
- 客户端 – BpBinder、IPCThreadState
- 服务端 – BBinder、IPCThreadState
各层各元素间的相互作用
同层元素相互对应、相互作用。
- 服务层IFooService向两端提供统一的foo()接口
- RPC层的服务代理与服务Stub支持Binder RPC操作
- IPC层的BpBinder与BBinder支持Binder IPC操作
类的结构
- IBinder – Android Binder类的抽象
- BBinder – 接收RPC代码与数据,生成Binder节点
- BpBinder – 保存目标服务的Handle
- IInterface – 提供类型变换功能,将服务代理或服务Stub转换为IBinder类型
- BnInterface – 转换服务类
- BpInterface – 转换服务代理类
- ProcessState – 管理Binder Driver
- 拥有IPCThreadState – 支持Binder IPC通信
- 拥有Parcel
- 拥有IPCThreadState – 支持Binder IPC通信
按层划分类为:
- 服务层:IInterface, BnInterface, BpInterface, BpRefBase, 服务接口,服务类
- RPC层:服务代理类,服务Stub类
- IPC层:BBinder, BpBinder, IPCThreadState, ProcessState, Parcel
运行机制
服务接口 – IAudioFlinger – 定义通信接口
继承自IInterface, 增加了asInterface、getInterfaceDescriptor方法
服务 – AudioFlinger – 实现服务功能
单例模式,instantiate方法,实现IAudioFlinger接口。
服务Stub – BnAudioFlinger – 处理服务的RPC代码与数据
继承自BnInterface,调用onTransact方法处理RPC代码与数据,该类继承IAudioFlinger和BBinder接口。
BBinder执行transact方法,处理基本的RPC代码,触发onTransact调用。
服务代理 – BpAudioFlinger
继承自BpInterface,该类继承IAudioFlinger各BpRefBase接口
BpRefBase接口继承自IBinder。
IAudioFlinger与IBinder类型转换
- IInterface.asBinder(): IAudioFlinger → IBinder
- BBinder(服务) – BnInterface.onAsBinder
- BpBinder(服务代理) – BpInterface.onAsBinder
- IAudioFlinger.asInterface(): IBinder → IAudioFlinger
- AudioFlinger(服务)
- BpAudioFlinger(服务代理)
本地服务管理器
- C/C++层Service Manager – Context Manager代理
- Java层Service Manager – C/C++层Service Manager代理
服务注册时,是ServiceManager向Context提出服务注册请求,BpServiceManager是服务代理,服务Stub是Context Manager处理,而非BnServiceManager,与普通服务不一致。
本地服务器主要成员函数:
- getService()
- addService()
- checkService()
- listService()
编写本地服务
客户端源码:frameworks/base/cmds/helloworld
服务端头文件:frameworks/base/include/helloworld
服务端源码:frameworks/base/libs/helloworld
服务接口-IHelloWorldService.h
- 定义HelloWorldService使用的RPC代码
- 定义服务接口宏DECLARE_META_INTERFACE
- 定义服务函数
服务Stub-BnHelloWorldService.h
- 继承BnInterface接口
- 重定义BBinder类的onTransact方法
- 增加HelloWorldService使用的RPC代码判断
- 检查接口
- 读取RPC数据
- 调用服务函数
服务-HelloWorldService.h
- 实现服务接口宏IMPLEMENT_META_INTERFACE – 实现类
- 继承BnHelloWorldService
- 实现服务函数
- 私有化构造函数,增加instantiate方法
- 服务注册
服务代理-BpHelloWorldService.h
- 继承BpInterface接口
- 实现服务函数代理
- 将服务接口名称保存到数据中
- 将服务函数参数保存到数据中
- 调用BpBinder类的transact方法
- 读取服务函数调用返回结果
服务开启-main_helloworldservice.cpp
- main方法
- 实例化HelloWorldService
- ProcessState创建线程池
- ProcessState加入线程池
服务调用-main_helloworldclient.cpp
- main方法
- 获取Service Manager代理
- 检索服务 – 因为不确定服务开启时间,要做等待判断
- 接口转换
- 调用服务代理函数
本地系统服务分析
相机服务
本地系统服务之一
兼容性定义文档:CDD(Compatibility Definition Document)
兼容性测试套件:CTS(Compatibility Test Suit)
相机应用程序
- 权限 – android.permission.CAMERA
- 预览界面 – Preview
- 继承自SurfaceView
- 实现SurfaceHolder.Callback接口
- surfaceCreated() – camera.open
- surfaceChanged() – camera.setParameters/startPreview
- surfaceDestoryed() – camera.stopPreview/release
相机服务框架
层次结构
应用框架层
- android.view.SurfaceView
- android.hardware.Camera
- android.media.MediaRecorder
本地库
- SurfaceFlinger
- Camera – android.hardware.Camera通过JNI调用
- CameraService – Camera服务连接
- CameraHardwareInterface – 定义服务框架层访问相机设备接口
- Special Camera –相机实现
- MediaRecorder – 与Camera交互
- V4L2 – 视频截取实现
内核
- Frame buffer Driver
- Special Camera Driver
- V4L2 Kernel Driver
框架类
服务接口
- ICameraService – 应用程序与相机服务间的连接
- ICamera – 相机设备的设置、控制
- ICameraClient – 相机设备的事件处理
服务Stub
- BnCameraService
- BnCamera
- BnCameraClient
服务
- CameraService – 继承BnCameraService
- 创建BpCameraClient实例
- 创建CameraService::Client实例
- CameraService::Client – 继承BnCamera
- 创建CameraHardwareInterface实例
- 持有BpCameraClient实例
- Camera – 继承BnCameraClient
- android.hardware.Camera的JNI调用对象
- 创建BpCameraService实例
- 创建BpCamera实例
服务代理
- BpCameraService
- BpCamera
- BpCameraClient
相机服务框架的运行
服务启动
相机服务在Media Server中初始化。Media Server是初始化大部分本地系统服务的Service Server。
- 初始化CameraService
- 注册到Context Manager
相机连接
- android.hardware.Camera.open()
- Camera.connect()
- 创建Camera实例
- 检索CameraService的Handle服务号,获取BpCameraService实例
- 调用BpCameraService的connect方法
- BnCameraService::onTransact方法
- 转换为BpCameraClient实例
- 调用CameraService::connect方法,获得BpCamera实例
- 创建CameraService::Client对象,调用Client构造函数
- 保存CameraService实例
- 保存BpCameraClient实例对象
- openCameraHardware初始化设备
- 保存并返回BpCamera实例
- 创建CameraService::Client对象,调用Client构造函数
- 返回BpCamera实例
- BnCameraService::onTransact方法
- 返回Camera实例
相机设置与控制
- android.hardware.Camera.setParameters()
- Camera.setParameters()
- BpCamera调用setParameters()
- BnCamera.onTransact()
- CameraService::Client::setParameters()
- CameraHardwareInterface的setParameters()
- CameraService::Client::setParameters()
- BnCamera.onTransact()
- BpCamera调用setParameters()
- Camera.setParameters()
相机事件处理
Shutter事件产生后,事件处理过程:
- CameraHardwareInterface触发Shutter事件
- 回调CameraService::Client的handleShutter()函数
- BpCameraClient调用notifyCallback传递Shutter事件
- BnCameraClient调用Camera::notifyCallback处理消息
- 调用CameraListener的notify转发Shutter事件给应用程序
- BnCameraClient调用Camera::notifyCallback处理消息
- CameraHardwareInterface关闭Shutter消息类型
- BpCameraClient调用notifyCallback传递Shutter事件
- 回调CameraService::Client的handleShutter()函数
Java服务框架
简介
与本地服务框架的不同点:
- 服务生成
- 继承Binder类,AIDL定义服务接口,aidl工具根据AIDL生成服务类、服务Stub和服务代理
- 继承Service类,适用于周期性的后台任务
- Binder IPC的处理
- Java服务框架通过JNI使用本地服务框架中的相应组成部分
- Java服务管理
- 与本地系统服务一致,注册到Context Manager
- 由Activity Manager Service管理
框架的层次结构
服务层
由于框架层的ServiceManager是非公开的,因此开发时无法使用ServiceManager直接检索服务,故提供了服务代理包装类FooManager,由ContextImpl.getSystemService()获取,其方法内部实际是通过ServiceManager检索服务,获取服务代理,保存在创建FooManager类中。
IFooService由aidl工具根据AIDL自动生成。
- 客户端:IFooService, FooManager
- 服务端:IFooService, FooService
RPC层
aidl工具自动生成服务代理和服务Stub。
- 客户端:IFooService.Stub.Proxy
- 服务端:IFooService.Stub
IPC层
本地服务框架使用BpBinder和BBinder来支持Binder IPC。Java服务框架使用JNI方式调用本地服务框架类来实现Binder IPC支持。
客户端:BinderProxy
- BinderProxy.transact() → BpBinder.transact()
服务端:Binder
- JavaBBinder.transact() → Binder.execTransact()
- JavaBBinder继承BBinder类,实现Binder.execTransact()调用
框架初始化
app_process进程启动时,AndroidRuntime类调用startReg()函数,加载JNI函数到虚拟机。
register_android_os_Binder()函数注册Java服务框架有关的本地函数。
- register_android_os_Binder()
- register_android_os_BinderInternal()
- register_android_os_BinderProxy()
- register_android_os_Parcel()
Java系统服务的实现
以闹钟服务为例。
服务接口-IAlarmManager
继承自IInterface(Java)类,aidl自动生成。
服务Stub-AlarmManagerService.Stub
继承IAlarmManager和Binder类,aidl自动生成。
重写Binder类的onTransact()方法,实现闹钟服务的RPC处理功能。
类似于本地服务框架中的BnAlarmManagerService。
服务-AlarmManagerService
继承服务Stub,实现服务接口具体功能。
服务代理-AlarmManagerService.Stub.Proxy
继承IAlarmManager和Binder类,aidl自动生成。
类似于本地服务框架中的BpAlarmManagerService。
服务代理包装类-AlarmManager
Service Manager(Java)包装类,实现服务检索。
ContextImpl.getAlarmManager()方法获取服务代理,返回服务代理包装类。
本地服务框架连接类-BinderInternal
BinderInternal为静态类,提供获取BpBinder对象的功能,BpBinder对象指向Context Manager。
getContextObject()获取BpBinder对象。
实际也是通过ProcessState的getContextObject()函数获取BpBinder对象,调用javaObjectForIBinder()生成BinderProxy对象。
Java Service Manager运行
服务注册
- SystemServer的ServerThread创建并注册AlarmManagerService
- ServiceManager.addService()
- getIServiceManager().addService()
- ServiceManagerNative.asInterface()
- 参数为BinderInternal.getContextObject()
- IServiceManager.queryLocalInterface()
- 创建并返回ServiceManagerProxy()
- ServiceManagerNative.asInterface()
- getIServiceManager().addService()
- ServiceManager.addService()
服务检索与使用
- ContextImpl.getSystemService()
- ServiceManager.getService()
- IBinder对象的缓存中检索服务
- getIServiceManager().getService()
- IAlarmManager.Stub.asInterface
- 生成并返回AlarmManager
- ServiceManager.getService()
使用AIDL生成服务代理与服务Stub
使用AIDL实现IPC服务的步骤:
- 使用AIDL语法定义服务接口
- 在frameworks/base/Android.mk的LOCAL_SRC_FILES中添加aidl文件
- 继承Stub类,实现具体的服务接口方法
- 在SystemServer中的ServerThread的run方法中创建并注册服务
- 创建服务代理包装类,在ContextImpl.getSystemService中添加条件判断
- 在ContextImpl中编写获取服务代理包装类的方法
- 调用make update-api命令更新frameworks/base/api/current.xml文件,公开服务代理包装类
AIDL语法
支持的数据类型
- Java基本类型,String,CharSequence、AIDL生成的接口类型或Parcelable类型
- List, Map容器类型,元素必须上面支持的数据类型
声明
- interface
- oneway interface – 不需应答,直接调用返回
类型控制
- in – 强制输入类型
- out – 强制输出类型
- inout – 强制输出输出类型
Java系统服务运行分析
Activity Manager Service
生成Android应用程序Activity和服务,管理它们的生命周期。
Remote Service生成过程:
- activity.start/bindService()
- Activity Manager Service向Zygote请求生成用于运行服务的ActivityThread
- Zygote接收请求后,创建新进程,加载ActivityThread
- ActivityThread启动RemoteService服务
Activity Manager Service创建服务分析
startService请求生成ActivityThread过程:
- activity.startService()
- ContextWrapper类,实际是ContextImpl的startService方法
- ActivityManagerProxy发起startService调用请求
- ActivityManagerNative.getDefault()获取ActivityManagerProxy对象
- ActivityManagerNative处理startService调用请求
- 获取ApplicationThreadProxy对象作为参数
- ActivityManagerService调用startService()
- startServiceLocked()
- retrieveServiceLocked()返回ServiceLookupResult
- serviceLookupResult.record取得ServiceRecord对象
- bringUpServiceLocked()
- getProcessRecordLocked()返回ProcessRecord
- 无需生成Process: realStartServiceLocked(),调用返回
- 要生成:startProcessLocked(), pendingServices.add()
- 创建ProcessRecordLocked()
- processNames记录进程名、应用uid、ProcessRecord
- startProcessLocked()
- packageManager.getPackageGids()
- Process.start()
- pidsSelfLocked存储pid和ProcessRecord的对应关系
- startServiceLocked()
ActivityThread启动过程:
Zygote会接收运行指定类的请求,创建新进程,加载指定类到进程中,调用类的main()方法。
- 消息队列
- Looper.prepareMainLooper() – 生成
- Looper.loop() – 运行
- ActivityThread对象
- 创建ActivityThread对象
- 调用attach()方法
- ActivityManagerProxy.attachApplication()
- ActivityManagerNative.getDefault()取得服务代理对象
- ActivityManagerNative.attachApplication()
- ActivityManagerService.attachApplication()
- attachApplicationLocked()
- pidsSelfLocked获取pid对应的ProcessRecord
- 连接ProcessRecord和IApplicationThreadProxy对象
- 移除pendingService中对象
- realStartServiceLocked完成服务启动
- attachApplicationLocked()
- ActivityManagerProxy.attachApplication()
Service启动过程:
- ActivityManagerService.realStartServiceLocked启动服务
- ApplicationThreadProxy.scheduleCreateService()
- ApplicationThreadNative.scheduleCreateService()
- ApplicationThread.scheduleCreateService()
- 创建CreateServiceData()保存IBinder和服务信息
- queueOrSendMessage()
- ativityThread.handleCreateService()
- getPackageInfoNoCheck()
- packageInfo.getClassLoader()
- classLoader.newInstance()
- service.onCreate()
- ativityThread.handleCreateService()
服务接口:
- IActivityManager – 控制组件运行、管理Activity生命周期
- ActivityManagerProxy
- ActivityManagerNative
- IApplicationThread – 与ActivityThread位于同一进程,接收AMS控制命令,实际控制操作由ActivityThread完成
- activityThread.getApplicationThread()