大道废

一切有为法,如梦幻泡影,如露亦如电,当作如是观.

0%

Android 设计与实现 学习笔记

Table of Contents

  1. Android 设计与实现 学习笔记
    1. JNI
      1. JNI方法全名规则
      2. JNI引用类型与JAVA引用类型的转化关系
      3. JNI方法签名规则
      4. JNI操作域与方法的函数
      5. JNI引用
      6. JNI异常处理
    2. 启动
      1. 启动流程
      2. 内核引导阶段
      3. 内核启动阶段
      4. init进程执行过程
      5. init.rc文件
      6. 执行Action,Service与属性服务
      7. 进入Java世界
    3. Binder
    4. 消息通信篇
    5. Package Manager
      1. 结构
      2. 启动
      3. APK安装过程
    6. Activity Manager
      1. 机制与实现
      2. 应用程序Activity的启动和调度
      3. Activity Manager进程管理

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
GetField CallMethod GetStaticField CallStaticMethod
SetField CallNonvirtualMethod SetStaticField  

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 严重错误,退出

启动

启动流程

  1. 执行bootloader
  2. 调用startkernel进入内核启动阶段,最终启动用户空间的init程序
  3. init解析init.rc配置文件,开启zygote与ServiceManager两个守护进程。zygote为Android启动的第一个Dalvik虚拟机,ServiceManager是Binder通信的基础。
  4. zygote定义socket,用于接收ActivityManagerService启动应用程序的请求
  5. zygote虚拟机启动systemserver子进程
  6. systemserver进程的init1与init2阶段分别启动Native System Service和Java System Service
  7. 在systemserver中开启Android核心服务,并添加入ServiceManager中。设置系统为systemReady状态。
  8. ActivityManagerService与zygote中的Socket通信,通过zygote启动Home应用,进入系统桌面。
  9. zygote收到ActivityManagerService连接请求,执行runSelectLoopMode
  10. zygote处理请求通过forkAndSpecialize启动新的应用进程,并最终启动HOME

内核引导阶段

  • kernel/arch/arm/kernel/head.S
  • kernel/arch/arm/kernel/head-common.S

内核启动阶段

  1. kernel/init/main.c -> startkernel函数
  2. 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 [mode] [owner] [group] 创建路径为的目录
mount [\*] 挂载设备
setkey 暂时不可用
setprop 设置系统属性
setrlimit 设置资源限制,resource是当前要限制的资源,cur是软限制,max是硬限制
start 启动指定服务
stop 停止指定服务
symlink 创建指向的软连接
sysclktz westofgmt> 设置系统时钟基准
trigger 触发一个事件
write [\*] 打开路径为的一个文件,并写入一个或多个字符串
Option关键字 描述
critial 核心服务,在一定时间内退出多次,将导致系统重启到recovery mode
disabled 开机时禁用此服务,即开机时不会自动启动此服务,但是可以手动启动
setenv 为服务设置环境变量
socket [ []] 创建一个名为/dev/socket/的socket,然后把它的文件描述符传给启动程序。
  类型type的值为dgram或stream。perm表示该socket的访问权限;
  user和group表示该socket所属的用户各组,这两个参数默认为0
user 执行服务前切换到用户,此选项默认是root
group [\*] 执行服务前切换到组, 默认是root
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

    1. propertyserviceinitaction -> startpropertyservice 加载属性文件,创建Socket接收客户端请求
    2. queuepropertytriggersaction 触发所有以property: 开头的Action
    3. 通过SOCKET实现属性,通讯接口为propertyset, propertyget

进入Java世界

  1. 启动zygote虚拟机,通过属性系统获取虚拟机配置信息,调用JNICreateJavaVM方法创建虚拟机

  2. 注册JNI方法,registerjniprocs

  3. AndroidRuntime:start -> CallStaticVoidMethod -> ZygoteInit的main 进入Java环境

    1. 注册zygote的Socket, ZygoteInit -> registerZygoteSocket
    2. 预加载Class资源和Resource资源, preload -> preLoadClass, preLoadResources
      1. preLoadClass 加载 preloaded-classes 文件中指定的类
      2. preLoadResources 加载 drawable与color资源,定义在framework/base/core/res/res/values/arrays.xml
    3. ZygoteInit -> startSystemServer 启动systemserve进程
      1. 通过forkSystemServer -> systemserver子进程
      2. systemserver子进程 -> handleSystemServerProcess -> RuntimeInit.zygoteInit
        1. redirectLogStream
        2. commonInit 设置时区,Log配置,HTTP User-Agent,模拟器上的trace调试
        3. nativeZygoteInit 开启Binder通信
        4. invodeStaticMain -> com.android.server.SystemServer.main -> throw new ZygoteInit.MethodAndArgsCaller
    4. ZygoteInit.main -> catch(ZygoteInit.MethodAndArgsCaller) -> 执行MethodAndArgsCaller的run方法
      1. init1 -> 启动Native System Service
        • SurfaceFlinger, SensorService
        • AndroidRuntime -> SystemServer.init2
        • 初始化Binder通信
      2. init2 -> Java System Service
        • Looper.prepare()
        • EntropyService, PowerManagerService, ActivityManagerService, TelephonyRegistry, PackageManagerService, WindowManagerService
        • startSystemUi
        • Watchdog
    5. 执行runSelectLoopMode方法,通过Socket监听客户端请求。用runOnce处理请求
  4. 处理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

  1. 初始化Binder通信

  2. 将自身注册为Context管理者

  3. 循环处理IPC请求

  4. Server启动

    1. 创建ProcessState对象
    2. 获取servicemanager代理对象
      • Binder通信接口: IBinder, BBinder(Server对应的Binder对象), BpBinder(Client访问BBinder的代理对象)
      • Binder服务接口:Server端提供的服务,由IServiceManager提供
      • Proxy:BpInterface继承自BpRefBase,BpRefBase.mRemote指向Client的BpBinder对象。BpServiceManager实现服务接口中声明的方法
      • Stub:BnInterface,BnServerManager
    3. 注册Service
    4. Server进程开启线程池
  5. Binder在Native中的实现

  6. Binder在Java层中的实现

  7. Java系统服务注册过程

    BinderInternal.getContextObject -> IBinder -> ServiceManagerNative.asInteface -> sServiceManager -> addService

    1. BinderInternal.getContextObject
    2. ServiceManagerNative.asInterface
    3. ServiceManagerProxy.addService
      1. Java的Service对象写入Parcel中
      2. 使用transact方法进行ipc通信
  8. Client获取服务代理

    1. 获取服务的Proxy
    2. Proxy.Stub.asInterface
    3. new SomeServer(SomeServerInterface, Thread)
  9. Client调用Java系统服务的方法

  10. AIDL

消息通信篇

  1. Handler.post(Runnable r) -> Handler.sendMessageDelayed(getPostMessage(r), 0) -> Message m.callback = r
  2. Handler.dispatchMessage -> msg.callback != null -> callback
    -> msg.handleMessage != null -> callback.handleMessage
    -> handleMessage
  3. MessageQueue.IdleHandler
  4. Message.recycle
  5. 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

启动

  1. SystemServer.Init2() -> ServerThread.run() -> PackageManagerService.main()
  2. PackageManagerService pms = new PackageManagerService(context, factoryTest, onlyCore)
  3. 创建并初始化Setting对象
  4. 获取系统默认设置
  5. 启动PackageHandler
  6. 创建data目录并初始化UserManager
  7. 解析data/system目录下的package.xml、packages-backup.xml
  8. dexopt优化
  9. 启动FileObserver监控APK文件的目录
  10. 调用scanDirLI扫描并安装APK
  11. 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

  1. FileObserver监控

    • system/framework
    • system/app
    • vendor/app
    • data/app
    • data/app-private
  2. 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:一个可以维护全局的应用程序状态的基类

  1. 初始化一个单例的Context对象,使其与Resource、LoadApk、ActivityThread、ApplicationContentResolver关联
  2. 创建Application对象,并与Context关联
  3. 创建ActivityStack类,管理Activity栈并维护其状态
  4. startRunning
  5. ActivityManagerService.setSystemProcess
  6. installSystemProviders
  7. 查询、安装Content Provider -> publishContentProvider
  8. systemReady
    1. 发送ACTIONPREBOOTCOMPLETED广播:CalendarProvider、ContactsProvider、MediaProvider
    2. 清理预启动的非persistent进程
    3. 读取Settings配置: alwaysfinishactivities
    4. Runnable回调接口:SystemUIService、BatteryService、NetworkManagementService、Watchdog
    5. 启动persistent应用和Home
    6. 发送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:
    1. ActivityRecord.affinity == Activity.affinity
    2. ActivityRecord.Task.Intent.Component == Activity.Component
    3. ActivityRecord.Task.affinityIntent.Component == Activity.Component
  • 目标为singleInstance,ActivityRecord.Task.Intent.Component == Activity.Component

启动Activity的第二个阶段为Pause

  1. ActivityStack.startPausingLocked
  2. schedulePauseActivity
  3. handlePauseActivity
  4. performPauseActivity
  5. activityPaused
  6. completedPauseLocked

启动应用程序进程

  • 会根据新的Activity是否占满屏来决定前一个Activity是否可见
  • 如果systemReady 没有设为true,则先启动的应用程序都加入mProcessesOnHold列表中等待

加载应用程序Activity

  • ActivityThread.main创建出程序主线程
  • ActivityThread.attch将应用程序加入到ActivityManagerService中
  • ActivityManagerService.attachApplication
  • ApplicationThread.bindApplication
  • ActivityThread.handleBindApplication
    1. 设置进程名
    2. 低内存设备禁用硬件加速
    3. 创建应用程序对应的Application
    4. 安装ContentProvider
    5. Instrumentation的onCreate方法
    6. Application的onCreate方法

显示Activity

  1. ActivityStack.realStartActivityLocked:加载Activity,onCreate,onStart,onResume。会通过WindowManagerService冻结屏幕并设置Activity可见。

  2. handleLaunchActivity -> performLaunchActivity -> newActivity -> makeApplication -> init -> attach -> callActivityOnCreate -> performCreate -> onCreate -> performStart -> callActivityOnStart -> onStart -> callActivityOnPostCreate -> onPostCreate

  3. handleResumeActivity -> performResumeActivity -> onResume 控制可见性,如果在onResume时,又启动另一个Activity则窗口变不可见,黑屏可能由此来。onResume之前可能会有onNewIntent与onActivityResult调用

  4. 如果当前Activity处于stop状态,onRestart -> onStart -> onResume -》onPostResme

  5. Activity.finish只是标志一下Activity处于完成的状态,会在IdleHandle线程中销毁

停止源Activity,在目标Activity的onCreate、onStart、onResume、activityIdleInternal执行后,开始停止源Activity。

  1. FLAGACTIVITYNOHISTORY启动标记的Activity是不会被放入栈中的
  2. onSaveInstanceState -》 onStop
  3. 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的进程,占用内存越大的越容易被杀
  • 未达到最小内存阈值的最大值时,不会杀