Table of Contents
Android 设计与实现 学习笔记
JNI
JNI方法全名规则
java方法:public static native boolean isLoggable(String tag, int level)
JNI方法:static jboolean androidutilLogisLoggable(JNIEnv* env, jobject clazz, jstring tag, jint level)
JNI引用类型与JAVA引用类型的转化关系
Java类型 | JNI类型 |
---|---|
java.lang.Class | jclass |
java.lang.String | jstring |
java.lang.Throwable | jthrowable |
object[] | jobjectArray |
boolean[] | jbooleanArray |
byte[] | jbyteArray |
char[] | jcharArray |
short[] | jshortArray |
int[] | jintArray |
long[] | jlongArray |
float[] | jfloatArray |
double[] | jdoubleArray |
JNI方法签名规则
Java类型 | 类型签名 |
---|---|
boolean | Z |
byte | B |
chat | C |
long | J |
float | F |
double | D |
short | S |
int | I |
类 | L全限定类名; |
数组 | [元素类型签名 |
JNI操作域与方法的函数
访问对象域 | 调用实例方法 | 访问静态域 | 调用静态方法 |
---|---|---|---|
GetFieldID | GetMethodID | GetStaticFieldID | GetStaticMethodID |
Get |
Call |
GetStatic |
CallStatic |
Set |
CallNonvirtual |
SetStatic |
JNI引用
引用类型 | 是否增加引用计数 | 作用范围 | 生命周期 |
---|---|---|---|
局部引用 | 可以增加引用计数 | 本线程 | 一次Native调用,只在创建它的Native方法的线程中有效,并且只在Native方法的一次调用中有效,在方法返回后,被回收 |
全局引用 | 可以增加引用计数 | 多线程 | 多个Native方法,生命周期到显式释放。通过引用JNI函数NewGlobalRef创建,通过DeleteGlobalRef释放 |
弱全局引用 | 不能增加引用计数 | 多线程 | 生命周期到显式释放。通过NewWeakGlobalRef创建,通过DeleteWeakGlobalRef释放,通过IsSameObject判断是否被回收 |
if (env->isSameObject(weakref, NULL) == JNITRUE) 那么引用被释放
全局引用,默认不能超过2000个。如果超过,在logcat中会看到”GREF overflow”
JNI异常处理
检查异常的方法有:
- 检查上一次JNI函数调用的返回值是否为NULL
- 通过调用JNI函数ExceptionOccurred()来判断是否发生异常
检查到异常后必须予以处理:
- 立即返回,异常会在Java代码中抛出
- 调用ExceptionClear()来清除异常
JNI异常处理函数 | 功能描述 |
---|---|
Throw | 抛出现有异常 |
ThrowNew | 抛出新的异常 |
ExceptionOccurred | 判断是否发生异常,并获得异常的引用 |
ExceptionCheck | 判断是否发生异常 |
ExceptionDescribe | 异常堆栈信息 |
ExceptionClear | 清除一个未处理的异常 |
FatalError | 严重错误,退出 |
启动
启动流程
- 执行bootloader
- 调用startkernel进入内核启动阶段,最终启动用户空间的init程序
- init解析init.rc配置文件,开启zygote与ServiceManager两个守护进程。zygote为Android启动的第一个Dalvik虚拟机,ServiceManager是Binder通信的基础。
- zygote定义socket,用于接收ActivityManagerService启动应用程序的请求
- zygote虚拟机启动systemserver子进程。
- systemserver进程的init1与init2阶段分别启动Native System Service和Java System Service
- 在systemserver中开启Android核心服务,并添加入ServiceManager中。设置系统为systemReady状态。
- ActivityManagerService与zygote中的Socket通信,通过zygote启动Home应用,进入系统桌面。
- zygote收到ActivityManagerService连接请求,执行runSelectLoopMode
- zygote处理请求通过forkAndSpecialize启动新的应用进程,并最终启动HOME
内核引导阶段
- kernel/arch/arm/kernel/head.S
- kernel/arch/arm/kernel/head-common.S
内核启动阶段
- kernel/init/main.c -> startkernel函数
- restinit -> kernelinit与kthreadd进程
kernelinit -> initpost -> /init 程序,或:/sbin/init, /etc/init, /bin/init, /bin/sh -> runinitprocess
init进程执行过程
- 创建 /proc, /sys, tmpfs, /dev/pts, /dev/socket, devpts, proc, sysfs 这些目录
- 解析init.rc初始化文件
- 触发build in的Action -> queuebuiltinaction, 这些action并没有在init.rc或者init.
.rc中配置 - 重新启动异常退出的Service
- 监听来自属性服务property service
- 监控signal,接收子进程异常退出后抛出的SIGCHLD信号,回收子进程资源或者重启子进程
- 监听来自keychord设备的事件
init.rc文件
- 基本概念:Section, Action, Service, Trigger, Command, Option
- 基本关键字:on, service
- on -> Action
- service -> Service,Option指定何时,如何启动Service程序。Service由服务名,服务对应命令路径,命令参数组成
- Command -> Linux命令或者方法
- Trigger -> 自定义的触发条件
- Action -> on声明,Trigger触发的Command序列
Trigger关键字 | 描述 |
---|---|
boot | /init.conf被加载后的第一个trigger |
property: |
属性值改变为指定值时 |
device-added- |
添加设备时触发 |
device-removed- |
移除设备时触发 |
service-exited- |
指定服务存在时 |
Command关键字 | 描述 |
---|---|
exec |
执行路径为 |
export |
设置系统全局环境变量 |
ifup |
使用ifup启动名为 |
import |
解析导入的init配置文件,扩展当前的配置 |
hostname |
设置主机名 |
chdir |
切换工作目录 |
chmod |
修改文件访问权限 |
chown |
修改文件所有者和组 |
chroot |
改变程序执行所参考的根目录 |
classstart |
启动指定类别的所有服务 |
classstop |
停止指定类别的所有服务 |
domainname |
设置域名 |
insmod |
加载路径为 |
mkdir |
创建路径为 |
mount |
挂载设备 |
setkey | 暂时不可用 |
setprop |
设置系统属性 |
setrlimit |
设置资源限制,resource是当前要限制的资源,cur是软限制,max是硬限制 |
start |
启动指定服务 |
stop |
停止指定服务 |
symlink |
创建指向 |
sysclktz |
设置系统时钟基准 |
trigger |
触发一个事件 |
write |
打开路径为 |
Option关键字 | 描述 |
---|---|
critial | 核心服务,在一定时间内退出多次,将导致系统重启到recovery mode |
disabled | 开机时禁用此服务,即开机时不会自动启动此服务,但是可以手动启动 |
setenv |
为服务设置环境变量 |
socket |
创建一个名为/dev/socket/ |
类型type的值为dgram或stream。perm表示该socket的访问权限; | |
user和group表示该socket所属的用户各组,这两个参数默认为0 | |
user |
执行服务前切换到用户 |
group |
执行服务前切换到组 |
oneshot | 服务只启动一次,一旦关闭就不能再启动 |
class |
为服务指定一个类别,默认为default, 同一类别的服务必须一起启动和停止 |
onrestart |
当服务重启时,执行一个Command |
执行Action,Service与属性服务
init.c中的executeonecommand, servicestart
init.c -> main -> actionforeachtrigger -> builtins.c中的doclassstart -> servicestartifnotdisabled
init.c -> main -> propertyinit() 属性服务内存共享区分配 -> propertyloadbootdefaults加载/default.prop文件中的属性 -> propertyserviceinit -> queuepropertytriggers
- propertyserviceinitaction -> startpropertyservice 加载属性文件,创建Socket接收客户端请求
- queuepropertytriggersaction 触发所有以property: 开头的Action
- 通过SOCKET实现属性,通讯接口为propertyset, propertyget
进入Java世界
启动zygote虚拟机,通过属性系统获取虚拟机配置信息,调用JNICreateJavaVM方法创建虚拟机
注册JNI方法,registerjniprocs
AndroidRuntime:start -> CallStaticVoidMethod -> ZygoteInit的main 进入Java环境
- 注册zygote的Socket, ZygoteInit -> registerZygoteSocket
- 预加载Class资源和Resource资源, preload -> preLoadClass, preLoadResources
- preLoadClass 加载 preloaded-classes 文件中指定的类
- preLoadResources 加载 drawable与color资源,定义在framework/base/core/res/res/values/arrays.xml
- ZygoteInit -> startSystemServer 启动systemserve进程
- 通过forkSystemServer -> systemserver子进程
- systemserver子进程 -> handleSystemServerProcess -> RuntimeInit.zygoteInit
- redirectLogStream
- commonInit 设置时区,Log配置,HTTP User-Agent,模拟器上的trace调试
- nativeZygoteInit 开启Binder通信
- invodeStaticMain -> com.android.server.SystemServer.main -> throw new ZygoteInit.MethodAndArgsCaller
- ZygoteInit.main -> catch(ZygoteInit.MethodAndArgsCaller) -> 执行MethodAndArgsCaller的run方法
- init1 -> 启动Native System Service
- SurfaceFlinger, SensorService
- AndroidRuntime -> SystemServer.init2
- 初始化Binder通信
- init2 -> Java System Service
- Looper.prepare()
- EntropyService, PowerManagerService, ActivityManagerService, TelephonyRegistry, PackageManagerService, WindowManagerService
- startSystemUi
- Watchdog
- init1 -> 启动Native System Service
- 执行runSelectLoopMode方法,通过Socket监听客户端请求。用runOnce处理请求
处理Home启动请求
ActivityManagerService.systemReady -> ActivityStack.resumeTopActivityLocked -> ActivityManagerService.startHomeActivityLocked -> ActivityStack.startActivityLocked -> ActivityStack.startActivityUncheckedLocked -> other startActivityLocked -> other resumeTopActivityLocked -> startSpecificActivityLocked -> startProcessLocked -> Process.start(“android.app.ActivityThread”) -> startViaZygote -> zygoteSendArgsAndGetResult -> Socket -> zygote -> runOnce -> handleChildProc -> android.app.ActivityThread.main
Binder
初始化Binder通信
将自身注册为Context管理者
循环处理IPC请求
Server启动
- 创建ProcessState对象
- 获取servicemanager代理对象
- Binder通信接口: IBinder, BBinder(Server对应的Binder对象), BpBinder(Client访问BBinder的代理对象)
- Binder服务接口:Server端提供的服务,由IServiceManager提供
- Proxy:BpInterface继承自BpRefBase,BpRefBase.mRemote指向Client的BpBinder对象。BpServiceManager实现服务接口中声明的方法
- Stub:BnInterface,BnServerManager
- 注册Service
- Server进程开启线程池
Binder在Native中的实现
Binder在Java层中的实现
Java系统服务注册过程
BinderInternal.getContextObject -> IBinder -> ServiceManagerNative.asInteface -> sServiceManager -> addService
- BinderInternal.getContextObject
- ServiceManagerNative.asInterface
- ServiceManagerProxy.addService
- Java的Service对象写入Parcel中
- 使用transact方法进行ipc通信
Client获取服务代理
- 获取服务的Proxy
- Proxy.Stub.asInterface
- new SomeServer(SomeServerInterface, Thread)
Client调用Java系统服务的方法
AIDL
消息通信篇
- Handler.post(Runnable r) -> Handler.sendMessageDelayed(getPostMessage(r), 0) -> Message m.callback = r
- Handler.dispatchMessage -> msg.callback != null -> callback
-> msg.handleMessage != null -> callback.handleMessage
-> handleMessage - MessageQueue.IdleHandler
- Message.recycle
- AsyncTask.execute -> executeOnExecutor(SerialExecutor, params) -> SerialExecutor.execute(mFuture)
- 会通过一个ThreadPoolExecutor来执行线程
Package Manager
- Permission, Permission Group信息的增加,删除,查询和检查
- 扫描并安装和卸载APK包,查询包的UID,GID,包名,系统默认程序
- 比较两个包的签名
- 查询Activity,Provider、Receiver、Service信息
- 查询Application、Package、Resouce、Shared、Library、Feature信息
- Intent匹配
结构
adb push -> adb install -r -l -s -> adb uninstall
Google Market、PackageInstaller.apk、第三方安装界面
PackageManager及其子类、adb与pm命令 -> binder通信 -> PackageManagerService方法
PackageManagerService及其相关类 Setting、Installer、FileObserver、DefaultContainerService
启动
- SystemServer.Init2() -> ServerThread.run() -> PackageManagerService.main()
- PackageManagerService pms = new PackageManagerService(context, factoryTest, onlyCore)
- 创建并初始化Setting对象
- 获取系统默认设置
- 启动PackageHandler
- 创建data目录并初始化UserManager
- 解析data/system目录下的package.xml、packages-backup.xml
- dexopt优化
- 启动FileObserver监控APK文件的目录
- 调用scanDirLI扫描并安装APK
- writeLPr更新package.xml, packages-backup.xml
uid >= FIRSTAPPLICATIONUID 或者 uid < FIRSTAPPLICATIONUID,FISTAPPLICATIONUID < 10000为系统程序UID。
用于为指定的组ID分配权限 - <assignpermission>用于为指定的用户ID分配指定的权限
指定的系统扩展库
- Hardware feature 指定当前设备支持的硬件特性:Audio、Bluetooth、Camera、Location、Microphone、NFC、Sensors、Screen、Telephony、Touchscreen、USB、WIFI。
- Software feature SIP VOIP
PackageManager的hasSystemFeature, getSystemAvailableFeatures
FileObserver监控
- system/framework
- system/app
- vendor/app
- data/app
- data/app-private
scanDirLI
- system/framework/
- system/app/
- vendor/app/
- data/app
- data/app-private
APK安装过程
- 读取目录
- 解析AndroidManifest.xml
Activity Manager
机制与实现
- 启动、杀死应用程序
- 启动并调度Activity生命周期
- 启动并调度应用程序Service生命周期
- 注册Broadcast Receiver,并接收和分发Broadcast
- 启动并发布Content Provider
- 调度Task
- 检查、授予、收回访问URI权限
- 处理crash
- 调整进程调度优先级及策略
- 查询当前系统运行状态
ActivityThread:管理应用程序所在进程的主线程的执行调度和运行Activities,broadcast
Instrumentation:应用程序测量工具基类,用于监控系统与应用程序间的交互
ContextImpl:context的通用实现类
Context2: 可以获取应用程序运行环境中的一些全局信息的接口
Application:一个可以维护全局的应用程序状态的基类
- 初始化一个单例的Context对象,使其与Resource、LoadApk、ActivityThread、ApplicationContentResolver关联
- 创建Application对象,并与Context关联
- 创建ActivityStack类,管理Activity栈并维护其状态
- startRunning
- ActivityManagerService.setSystemProcess
- installSystemProviders
- 查询、安装Content Provider -> publishContentProvider
- systemReady
- 发送ACTIONPREBOOTCOMPLETED广播:CalendarProvider、ContactsProvider、MediaProvider
- 清理预启动的非persistent进程
- 读取Settings配置: alwaysfinishactivities
- Runnable回调接口:SystemUIService、BatteryService、NetworkManagementService、Watchdog
- 启动persistent应用和Home
- 发送ACTIONBOOTCOMPLETED广播
应用程序Activity的启动和调度
Launcher.onClick -> Launcher.startActivitySafely -> Launcher.startActivity -> Launch.parent.startActivity -> Activity.startActivityForResult(requestCode = -1) -> Instrumentation.execStartActivity -> ActivityManagerProxy.startActivity -> BinderProxy.transact(STARTACTIVITYTRANSACTION)
ActivityManagerService.startActivityMayWait -> ActivityStack.startActivityLock -> ActivityStack.startActivityUncheckedLocked -> ActivityStack.startActivityLocked -> ActivityStack.resumeTopActivity
ActivityManagerService.startActivityMayWait
int index = indexOfTokenLocked -> resultCode = mHistory.get(index) -> sendActivityResultLocked
FLAGACTIVITYNEWTASK:
- sourceRecord == null (由Launch或者adb start)
- sourceRecord 启动模式为singleInstance
- 要启动的目标为singleInstance或者singleTask
用户行为导致Activity切换 -> 回调Activity.onUserLeaveHint
可利用Task:
- 目标非singleInstance:
- ActivityRecord.affinity == Activity.affinity
- ActivityRecord.Task.Intent.Component == Activity.Component
- ActivityRecord.Task.affinityIntent.Component == Activity.Component
- 目标为singleInstance,ActivityRecord.Task.Intent.Component == Activity.Component
启动Activity的第二个阶段为Pause
- ActivityStack.startPausingLocked
- schedulePauseActivity
- handlePauseActivity
- performPauseActivity
- activityPaused
- completedPauseLocked
启动应用程序进程
- 会根据新的Activity是否占满屏来决定前一个Activity是否可见
- 如果systemReady 没有设为true,则先启动的应用程序都加入mProcessesOnHold列表中等待
加载应用程序Activity
- ActivityThread.main创建出程序主线程
- ActivityThread.attch将应用程序加入到ActivityManagerService中
- ActivityManagerService.attachApplication
- ApplicationThread.bindApplication
- ActivityThread.handleBindApplication
- 设置进程名
- 低内存设备禁用硬件加速
- 创建应用程序对应的Application
- 安装ContentProvider
- Instrumentation的onCreate方法
- Application的onCreate方法
显示Activity
ActivityStack.realStartActivityLocked:加载Activity,onCreate,onStart,onResume。会通过WindowManagerService冻结屏幕并设置Activity可见。
handleLaunchActivity -> performLaunchActivity -> newActivity -> makeApplication -> init -> attach -> callActivityOnCreate -> performCreate -> onCreate -> performStart -> callActivityOnStart -> onStart -> callActivityOnPostCreate -> onPostCreate
handleResumeActivity -> performResumeActivity -> onResume 控制可见性,如果在onResume时,又启动另一个Activity则窗口变不可见,黑屏可能由此来。onResume之前可能会有onNewIntent与onActivityResult调用
如果当前Activity处于stop状态,onRestart -> onStart -> onResume -》onPostResme
Activity.finish只是标志一下Activity处于完成的状态,会在IdleHandle线程中销毁
停止源Activity,在目标Activity的onCreate、onStart、onResume、activityIdleInternal执行后,开始停止源Activity。
- FLAGACTIVITYNOHISTORY启动标记的Activity是不会被放入栈中的。
- onSaveInstanceState -》 onStop
- StopInfo通知ActivityManagerService停止Activity的操作完成
Activity Manager进程管理
非隐藏进程:
- 有可见但非前台的activity
- 有可见activity,该进程未被完全覆盖的Activity
- 处于Pausing和Paused状态的activity
- 处于STOPPING状态的Activity
- AMS.setProcessForeground
- HOME进程
- 运行在内核空间中的进程
- 当前线程的上一个线程
- 备份线程
/sys/module/lowmemorykiller/paramerters/adj 优先级数
/sys/module/lowmemorykiller/paramerters/minfree 对应的内存阀值
lowmemshrink:
- OOM adj越大的进程越容易被杀
- 相同OOM adj的进程,占用内存越大的越容易被杀
- 未达到最小内存阈值的最大值时,不会杀