《Android源码分析实录》读书笔记

z8g 于 2020-06-17 发布

[TOC]

1 硬件抽象层

硬件抽象层(Hardware Abstract Layer, HAL)在用户空间中运行,向下能够屏蔽硬件驱动模块的实现细节,向上能够提供硬件访问服务。

1.1 HAL层

Linux内核代码遵循GPL1协议,系统代码遵循Apache License 2协议,所以将对硬件的支持分别实现在内核空间和用户空间。

主要包含GPS(全球定位系统)、Vibrator(震动器)、Wi-Fi(无线局域网)、Copybit(2D硬件加速)、Audio(音频)、Camera(照相机)、Lights(头电筒)、RIL(Radio Interface Layer,无线接口层)、Overlay(资源替换机制)等模块。

1.2 HAL Module架构

HAL系统采用HAL Module和HAL Stub结合的形式,上层通过HAL Module提供的统一接口获取并操作HAL Stub,*.so文件只会被映射到一个进程,也不存在重复映射和重入问题。 HAL Module中分为如下三个结构体:

typedef struct hw_module_t {
	uint32_t tag;
	uint16_t module_api_version;
#define version_major module_api_version
	uint16_t hal_api_version;
#define version_minor hal_api_version
	const char *id;
	const char *name;
	const char *author;
	struct hw_module_methods_t *methods;
	void *dso;
	uint32_t reserved[32-7];
} hw_model_t;
typedef struct hw_module_methods_t {
	/* 用来打开硬件抽象层模块中的硬件设备 */
	int (*open)(const struct hw_model_t *module, const char *id,
				struct hw_device_t **device); 
} hw_module_methods_t;
typedef struct hw_device_t {
	uint32_t tag;
	uint32_t version;

	struct hw_module_t *module;
	uint32_t reserved[12];

	int (*close)(struct hw_device_t *device);
} hw_device_t;

1.3 hardware.c

hw_get_module()函数能够根据模块ID寻找硬件动态链接库的地址,然后调用函数load打开动态链接库,并从中获取硬件模块结构体的地址。 通过veriant_keys数组可以得到操作权限。


static const char *variant_keys[] = {
	"ro.harddware",
	"ro.product.board",
	"ro.board.platform",
	"ro.arch"
};

hw_get_module(const char *id, const struct hw_module_t **module)
{
	int status;
	int i;
	const struct hw_module_t *hmi = NULL;
	char prop[PATH_MAX];
	char path[PATH_MAX];

	for (i = 0; i < HAL_VARIANT_KEYS_COUNT + 1; i++) {
		if (i < HAL_VARIANT_KEYS_COUNT) {
			if (property_get(variant_keys[i], prop, NULL) == 0) {
				continue;
			}
			snprintf(path, sizeof(path), "%s/%s.%s.so", HAL_LABRARY_PATH, id, prop);
		} else {
			snprintf(path, sizeof(path), "%s/%s.default.so", HAL_LABRARY_PATH, id);
		}
		if (access(path, R_OK)) {
			continue;
		}
		break;
	}

	/* 载入相应的库,并把他们的HMI保存到module中 */
	status = -ENOENT;
	if (i < HAL_VARIANT_KEYS_COUNT + 1) {
		status = load(id, path, module);
	}
	return status;
}
/* 打开相应的库,并获得hw_module_t结构体 */
static int load(const char *id, const char *path, const struct hw_module_t **pHmi) {
	int status;
	void *handle;
	struct hw_module_t *hmi;
	handle = dlopen(path, RTLD_NOW); // 打开相应的库
	if (handle == NULL) {
		char const *err_str = dlerror();
		LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
		status = -EINVAL;
		goto done;
	}

	const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
	hmi = (struct hw_module_t *)dlsym(handle, sym); // 获得hw_module_t结构体
	if (hmi == NULL) {
		LOGE("load: couldn't find symbol %s", sym);
		status = -EINVAL;
		goto done;
	}

	if (strcmp(id, hmi->id) != 0) {
		LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
		status = -EINVAL;
		goto done;
	}

	hmi->dso = handle;

	/* 成功 */
	status = 0;

done:
	if (status != 0) {
		hmi = NULL;
		if (handle != NULL) {
			dlclose(handle);
			handle = NULL;
		}
	} else {
		LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p", id, path, *pHmi, handle);
	}

	*pHmi = hmi; // 得到hw_module_t

	return status;
}

1.4 硬件抽象层的加载过程

硬件抽象层模块由安卓系统统一加载,调用者指定ID即可,hw_get_module函数负责加载硬件抽象层模块。

1.5 分析硬件访问服务

硬件抽象层模块使用C__开发,硬件访问服务使用Java开发,通过JNI调用。

package android.os;

interface IFregService {
	void setVal(int val); // 往虚拟硬件设备freg的寄存器val中写入一个整数
	int getVal(); // 从freg的寄存器读出一个整数
}
package com.android.server;

import android.content.Context;
import android.os.IFregService;
import android.util.Slog;

public class FregService extends IFregService.Stub {
	private static final String TAG = "FregService";

	private int mPtr = 0;
	FregService() {
		mPtr = init_native();
		if (mPtr == 0) {
			Slog.e(TAG, "Failed to initialize freg service.");
		}
	}

	public void setVal(int val) {
		if (mPtr == 0) {
			Slog.e(TAG, "Freg service is not initialized");
			return;
		}
		setVal_native(mPtr, val);
	}

	public int getVal() {
		if (mPtr == 0) {
			Slog.e(TAG, "Freg service is not initialized");
			return;
		}
		return getVal_native(mPtr);
	}

	private static native int init_native();
	private static native void setVal_native(int ptr, int val);
	private static native int getVal_native(int ptr);
}

1.6 分析HAL层的具体实现(以Sensor系统为例)

传感器的Java部分,实现文件为Sensor*.java,代码路径为: frameworks/base/include/core/java/android/hardware

JNI部分,代码路径为: frameworks/base/core/jni/android_hardware_SensorManager.cpp

HAL层,头文件为: hardware/libhardware/include/hardware/sensors.h

驱动层,实现路径为: kernel/driver/hwmon/$(PROJECT)/sensor


Sensor编程的流程

(1) 获取系统服务

sensormanager = (SensorManager) getSystemService(SENSOR_SERVICE);

(2) 获取相应的Sensor类型的对象

sensorObject = sensormanager.getDefaultSensor(sensor Type);

(3) 声明一个SensorEventListener对象,用于监听Sensor事件,并重载onSensorChanged方法:

SensorEventListener sensorListener = new SensorEventListener() {};

(4) 注册相应的SensorService

sensormanager.registerListener(sensorListener, sensorObject, Sensor, TYPE);

(5) 销毁相应的SensorService sensormanager.unregisterListener(sensorListener, sensorObject);

2 JNI(本地方法接口)层

Java本地接口(JNI, Java Native Interface)允许Java与其他语言(主要是C/C++)交互。

2.1 与JNI相关的文件

./frameworks/base/media/java/android/media/MediaScanner.java
./frameworks/base/media/jni/android_media_MediaScanner.cpp
./frameworks/base/media/jni/android_media_MediaPlayer.cpp
./frameworks/base/media/jni/AndroidRuntime.cpp
./libnativehelper/JNIHelp.cpp

与JNI密切相关的是Media系统,Media系统的架构基础是MediaScanner,位于:

packages/providers/MediaProvider

该路径包含三个主要部分:

2.2 分析MediaScanner的Java层

在MediaScanner系统中,JNI的调用关系是: MediaScanner -> libmedia_jni.so -> libmedia.so Java层实现文件为:

./frameworks/base/media/java/android/media/MediaScanner.java

2.3 分析MediaScanner的JNI层

载入C组件:

public class MediaPlayer {
	static {
		System.loadLibrary("media_jni");
	}
}

将Native对象的指针保存到Java对象:

static const char* const kClassMediaScanner = "android/media/MediaScanner";
//...

/* native_init 的JNI层实现 */
static void android_media_MediaScanner_native_init(JNIEnv *env) {
	ALOGV("native_init");
	jclass clazz = env->FindClass(kClassMediaScanner);
	if (clazz == NULL) {
		return;
	}
	fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
	if (fields.context == NULL) {
		return;
	}
}

创建Native层的MediaScanner对象:

在文件android_media_MediaScanner.cpp中,函数android_media_MediaScanner_native_setup的功能是创建一个Native层的MediaScanner对象,但是此函数使用的是OpenCore提供的PVMediaScanenr。

static void android_media_MediaScanner_native_setup(JNIEnv *env, jobject thiz) {
	ALOGV("native_setup");
	MediaScanner *mp = new StatefrightMediaScanner;
	if (mp == NULL) {
		jniThrowException(env, kRunTimeException, "Out of memory");
		return;
	}
	env->SetIntField(thiz, fields.context, (int)mp);
}

2.4 分析MediaScanner的Native层

在安卓系统中使用JNINativeMethod定义Native函数:

typedef struct {
	const char *name; /* Java中函数的名字 */
	const char *signature; /* 描述了函数的参数和返回值 */
	void *fnPtr; /* 函数指针,指向C函数 */
} JNINativeMethod;
标识 Java类型 C类型
V void void
Z jboolean boolean
I jint int
J jlong int
D jdouble double
F jfloat float
B jbyte byte
C jchar char
S jshort short
[I jintArray int[]
[F jfloatArray float[]
[B jbyteArray byte[]
[C jcharArray char[]
[S jshortArray short[]
[D jdoubleArray double[]
[J jlongArray long[]
[Z jbooleanArray boolean[]

定义并注册JNINativeMethod数组,对应的实现代码如下所示:

/* 定义一个JNINativeMethod函数 */
static JNINativeMethod gMethods[] = {
	{
		"processDirectory",
		"(Ljava/lang/String;Landroid/media/MediaScannerClient;)V",
		"(void*)android_media_MediaSacnner_processDirectory"
	},
	{
		"processFile",
		"(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V",
		"(void*)android_media_MediaScanner_processFile"
	},
	// ...
};

int register_android_media_MediaScanner(JNIEnv *env) {
	return AndroidRuntime::registerNativeMethods(env, kClassMediaScanner, gMethods, NELEM(gMethos))
}

动态注册:

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
	JNIEnv *env = NULL;
	jint result = -1;

	if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
		ALOGE("ERROR: GetEnv failed\n");
		goto bail;
	}
}
if (register_android_media_MediaPlayer(env) < 0) {
	LOGE("ERROR: MediaPlayer native registeration failed\n");
	goto bail;
}

…..


基本数据类型的转换关系

Java Native类型 本地C类型 字长
boolean jboolean 无符号 8位
byte jbyte 无符号 8位
char jchar 无符号 16位

3 Android内存系统分析

内存也称为内存储器,其作用是暂时存放CPU中的运算数据以及与硬盘等外部存储器交换的数据。

3.1 Android的进程通信机制

Binder由Client、Server、Service Manager和Binder驱动程序(内核空间)组成,开发者只需要实现Client和Server组件即可。

Service Manager是Binder机制的上下文管理者,位于frameworks/base/cmds/servicemanager目录中,主要由binder.hbinder.cservice_manager.c 组成。

binder_open: 打开Binder设备文件 open: 打开设备文件/dev/binder misc_register: 创建设备文件 binder_proc: 保存打开设备文件进程的上下文信息 binder_mmap: 打开的设备文件进行内存映射操作 binder_update_page_range: 把一个物理页面同时映射到内核空间和进程空间

3.2 分析Ashmem驱动程序

匿名共享内存子系统Ashmem(Anonymous Shared Memory),以驱动程序的形式在内核空间中实现,具有以下两个特点:

其核心功能是实现创建(open)、映射(mmap)、读写(read/write)以及锁定和解锁(pin/unpin)


用到了ashmem_area、ashmem_range、ashmem_pin三个结构:

struct ashmem_area {
	char name[ASHMEM_FULL_NAME_LEN]; // 匿名共享内存的名称
	struct list_head unpinned_list; // 解锁内存列表
	struct file *file; // 指向临时文件系统tmpfs中的一个文件
	size_t size; // 文件大小
	unsigned long prot_mask; // 匿名共享内存的访问保护位
};
struct ashmem_range {
	struct list_head lru; // 最近最少使用的列表
	struct list_head unpinned;
	struct ashmem_area *asma;
	size_t pgstart; // 处于解锁状态内存的开始地址
	size_t pgend; // 处于解锁状态内存的结束地址
	unsigned int purged; // 解锁内存是否被收回
};
struct ashmem_pin {
	__u32 offset; // 这块内存的偏移值
	__u32 len; // 这块内存的大小
};
static struct file_operations ashmem_fops = {
	.owner = THIS_MODULE,
	.open = ashmem_open,
	.release = ashmem_release,
	.mmap = ashmem_mmap,
	.unlocked_ioctl = ashmem_ioctl,
	.compat_iotcl = ashmem_ioctl,
};

Ashmem在kernel/common/mm/ashmem.c中实现,初始化过程中会创建一个misc类型的设备文件/dev/ashmem,提供open、mmap、release、ioctl(input/output control)四种操作。

匿名共享内存创建功能呢是在文件frameworks/base/core/java/android/os/MemoryFile.java中实现的。

Ashmem不提供文件的read操作和write操作,如果进程要访问这个共享内存,则必须将这个设备文件映射到自己的进程空间中,才能进行内存访问。

通过调用JNI方法native_readnative_write实现读写匿名共享内存操作功能,都在frameworks/base/core/jni/android/os/MemeoryFile.cpp中定义。

锁定和解锁功能在文件kernel/common/include/linux/ashmeme.h中定义。

回收匿名内存块模块通过调用ashmem_shrink来执行内存回收,在kernel/goldfish/ashmem.c中实现。

3.3 分析C++访问接口层

3.4 分析Java访问接口层

3.5 内存优化机制

4 Android虚拟机系统详解

Android虚拟机系统是Dalvik VM,基于寄存器。 .dex格式是为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。

4.1 Android虚拟机基础

目录结构:

Dalvik的架构:

4.2 分析Dalvik的运作流程

Dalvik的相关可执行程序


初始化Dalvik虚拟机,Init.c


启动Zygote:


启动SystemServer进程:

(1)首先是启动各种系统服务

以下是SystemServer中启动的服务:

服务类名称(后缀为Service) 作用描述 启动模式
Entropy 提供伪随机数 1.0
PowerManager 电源管理服务 1.2/3
ActivityManager 最核心的服务之一,管理Activity 自定义
TelephonyRegistry 注册电话模块的事件响应,比如重启、关闭、启动等 1.0
PackageManager 程序包管理服务 3.3
AccountManager 账户管理服务,是指联系人账户,而不是Linux系统的账户 1.0
Content ContentProvider服务,提供跨进程数据交换 3.0
BatteryService 电池管理服务 1.0
Lights 自然光强度感应传感器服务 1.0
Vibrator 震动器服务 1.0
AlarmManager 定时器管理服务,提供定时提醒服务 1.0
WindowManager Framework最核心的服务之一,负责窗口管理 3.3
Bluetooth 蓝牙服务 1.0+
DevicePolicyManager 提供一些系统级别的设置及属性 1.3
StatusBarManager 状态栏管理服务 1.3
Clipboard 系统剪贴板服务 1.0
InputMethodManager 输入法管理服务 1.0
NetStat 网络状态管理 1.0
NetworkManagement 网络管理服务 NMS.create()
Connectivity 网络连接管理服务 2.3
Throttle 节流阀 1.3
AccessibilityManager 辅助管理程序截获所有的用户输入,并根据这些输入给用户一些额外的反馈,起到辅助作用 1.0
Mount 挂载服务,可通过该服务调用Linux层面的mount程序 1.0
NotificationManager 通知栏管理服务,Android中的通知栏和状态栏在一起,只是界面上前者在左边,后者在右边 1.3
DeviceStorageMonitor 磁盘空间状态检测服务 1.0
LocationManager 地理位置服务 1.3
SearchManager 搜索管理服务 1.0
DropBoxManager 通过该服务访问Linux层面的Dropbox程序 1.0
WallpaperManager 墙纸管理服务,墙纸不等同于桌面背景,在View系统内部,墙纸可以作为任何窗口的背景 1.3
Audio 音频管理服务 1.0
BackupManager 系统备份服务 1.0
AppWidget Widget服务 1.3
RecognitionManager 身份识别服务 1.3
DiskStats 磁盘统计服务 1.0

AmS的启动模式如下所示:

(2) 启动第一个Activity


加载class类文件

(1) DexFile在内存中的映射 主要由三部分组成:

映射到内存后,调用dexFileParse进行分析,分析结果存放于名为DexFile的数据结构

解析完毕后,开始加载Class文件,用ClassObject保存加载类,以下是相关的数据结构:

typedef struct Object {
	ClassObject *clazz;
	u4 lock;
};

struct DataObject {
	Object obj;
	u4 instanceData[1];
};

struct StringObject {
	Object obj;
	u4 instanceData[1];
}
//...

(2) ClassObject: Class在加载后的表现形式 加载过程会在内存中alloc几个区域,分别存放directMethods、virtualMethods、sfields、ifields。

(3) 加载Class并生成相应ClassObject的函数 负责加载工作的函数为findClassNoInit(),在获取Class索引时,会分基本类库文件和用户类文件两种情况,在grund.sh中:

export BOOTCLASSPATH=$bootpath/core.jar:$bootpath/ext.jar:$bootpath/framework.jar:$bootpath/android.police.jar

(4) 加载基本类库文件

main    JNI_CreateJavaVM    dvmStartup    dvmThreadObjectStartup    dvmFindSystemClassNoInit    findClassNoInit

(5) 加载用户类文件

4.3 Dalvik VM的内存系统

如何分配内存

对象布局:

堆:

堆内存位图:

堆的内存管理

dvmAllocObject

以下是dvmAllocObject的伪代码实现:

Object *dvmAllocObject(ClassObject *clazz, int flags) {
	n = get object size from class object clazz
	first try: allocate n bytes from heap
	if first try failed {
		run GC without collecting soft references
		second try: allocate n bytes from heap
	}
	if second try failed {
		third try: grow the heap and allocate n bytes from heap
	}
	if third try failed {
		run GC with collection soft references
		fourth try: grow the heap and allocate n bytes from heap
	}
	if fourth try failed {
		return null pointer, dalvik vm will abort
	}
}

分析内存管理机制的源码

Dalvik内存管理的实现源码保存在vm/alloc目录中 (1) 表示堆的结构体

typedef struct {
	mspace *msp; // 使用dlmalloc分配的内存
	HeapBitmap objectBitmap; 
	size_t absoluteMaxSize; // 堆可以增长的最大值
	size_t bytesAllocated; // 已分配的字节数
	size_t objectsAllocated; // 已分配的对象数
}

(2) 表示位图堆的结构体数据 在文件HeapBitmap.h中定义表示位图堆的结构体数据,其源码如下:

unsigned long int *bits; //位图数据
size_t bitsLen; //位图的大小
uintptr_t base; // 位图对应的对象指针地址的首地址
uintptr_t max; // 位图使用中的最后一位被设置的对象指针地址,如果全没设置则(max < base)

(3) HeapSource结构体 HeapSource.c中定义:

struct HeapSource {
	size_t targetUtilization;
	size_t mininumSize;
	size_t startSize;
	size_t absoluteMaxSize;
	size_t idealSize;
	size_t softLimit;
	Heap heaps[HEAP_SOURCE_MAX_HEAP_COUNT];
	size_t numHeaps;
	size_t externalBytesAllocated;
	size_t externalLimit;
	bool sawZygote;
}

(4) 与 mark bits 相关的结构体 MarkSweep.h:

typedef struct {
	const Object **limit;
	const Object **top;
	const Object **base;
} GcMarkStack;

typedef struct {
	HeapBitmap bitmap[HEAP_SOURCE_MAX_HEAP_COUNT];
	size_t numBitmaps;
	GcMarkStack stack;
	const void *finger;
} GcMarkContext;

(5) 结构体GcHelp HeapInternal.h中定义了Dalvik的垃圾回收机制,需要用到结构体GcHeap:

struct GcHeap {
	HeapSource *heapSource;
	HeapRefTable nonCollectableRefs;
	LargeHeapRefTable *finalizableRefs;
	Object *softReferences;
	Object *weakReferences;
	Object *phantomReferences;
	LargeHeapRefTable *referenceOperations;
	Object *heapWorkerCurrentObject;
	Method *heapWorkerCurrentMethod;
	u8 heapWorkerInterpStartTime;
	u8 heapWorkerInterpCpuStartTime;
	//...
};

(6) 初始化垃圾回收器 在Init.c中,通过函数dvmGcStartup()来初始化垃圾回收器:

bool dvmGcStartup(void) {
	dvmInitMutex(&gDvm.gcHeapLock);
	return dvmHeapStartup();
}

(7) 初始化与Heap相关的信息 在alloc/Heap.c中,通过dvmHeapStartup()函数来初始化和Heap相关的信息,例如常见的内存分配和内存管理等工作。

(8) 创建GcHeap 在文件alloc/HeapSource.c中,通过函数dvmHeapSourceStartup()来创建GcHeap

(9) 追踪位置 在文件alloc/HeapSource.c中,通过函数countAllocation()在Heap::object Bitmap上进行标记,以便追踪这些区域的位置。

(10) 分配空间 在文件Heap.c中,通过dvmMalloc()实现空间的分配工作,具体分配过程由tryMalloc函数控制:

tryMalloc()    gcForMalloc()    dvmCollectGarbageInternal()

4.4 分析Dalvik VM的启动过程

创建Dalvik VM实例:

指定控制选项:

创建并初始化Dalvik VM实例:

创建JNIEnvExt对象:

设置当前进程:

注册Android核心类的JNI方法:

使用线程创建javaCreateThreadEtc钩子:

4.5 创建Dalvik VM进程

分析底层启动过程:

初始化运行的Dalvik VM:

5 IPC(进程间)通信机制详解

Android系统中,应用程序都是由Activity和Service组成,其中Service通常运行在独立的进程中,Activity不但可以运行在同一个进程中,也可以运行在不同的进程中。不在同一个进程中的Activity和service通过Binder进程通信机制实现通信功能。

5.1 Binder机制概述

Binder是Android系统提供的一种IPC(进程间)通信机制。

Client、Server、ServiceManager之间的交互关系如下:

5.2 分析Binnder驱动程序

Binder采用AIDL(Android Interface Description Language)来描述进程间通信的接口。


分析数据结构

(1) binder_work binder_work表示在Binder驱动中进程所要处理的工作项,定义代码如下所示:

struct binder_work {
	struct list_head entry; // 双向链表
	enum {
		BINDER_WORK_TRANSACTION = 1,
		BINDER_WORK_TRANSACTION_COMPLETE,
		BINDER_WORK_NODE,
		BINDER_WORK_DEAD_BINDER,
		BINDER_WORK_DEAD_BINDER_AND_CLEAR,
		BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
	} type;
};

(2) binder_node binder_node用来定义Binder实体对象,每一个Service组件在Binder驱动程序中都有一个Binder实体对象。

struct binder_node {
	/* 用于调试 */
	int debug_id;
	/* 当本节点引用计数发生改变,需要通知所属进程时,
	   通过该成员挂入所属进程的to-do队列里,唤醒所属进程执行Binder实体引用计数的修改 */
	struct binder_work work;
	/* 每个进程都维护一颗红黑树,以Binder实体在用户空间的指针,即本结构的ptr成员为索引存放该进程所有的Binder实体。
	这样驱动可以根据Binder实体在用户空间的指针很快找到其位于内核的节点。
	rb_node用于将本节点链入该红黑树中。
	销毁节点时,须将rb_node从红黑树中摘除,但如果本节点还有引用没有切断,就用dead_node将节点隔离到另一个链表中,直到通知所有进程切断与该节点的引用后,该节点才可能被销毁。
	*/
	union {
		struct rb_node rb_node;
		struct hlist_node dead_node;
	}; 
	struct binder_proc *proc; // 指向节点所属的进程
	struct hlist_head refs; // 队列头,所有指向本节点的引用都链接在该队列里。这些引用隶属于不同的进程,通过该队列可以遍历指向该节点的所有引用。
	int internal_strong_refs;
	int local_weak_refs;
	int local_strong_refs;
	void __user *ptr;
	void __user *cookie;
	unsigned has_strong_ref:1;
	unsigned pending_strong_ref:1;
	unsigned has_weak_ref:1;
	unsigned pending_weak_ref:1;
	unsigned has_async_transaction:1;
	unsigned min_priority:8;
	struct list_head async_todo;
};

(3) binder_ref 结构体binder_ref用来描述一个Binder引用对象,在Android系统中,每一个Client组件在Binder驱动程序中都有一个Binder引用对象。

struct binder_ref {
	int debug_id;
	struct rb_node rb_node_desc;
	struct rb_node rb_node_node;
	struct hlist_node node_entry;
	struct binder_proc *proc;
	struct binder_node *node;
	uint32_t desc;
	int strong;
	int weak;
	struct binder_ref_death *death;
};

(4) binder_ref_death binder_ref_death是一个通知结构体,只要某进程对某Binder引用订阅了其实体的死亡通知,那么Binder驱动将会为该Binder引用建立一个binder_ref_death通知结构体,保存到death中:

struct binder_ref_death {
	struct binder_work_work;
	void __user *cookie;
};

(5) binder_buffer 内核缓冲区,能够早进程之间传输数据:

struct binder_buffer {
	struct list_head entry;
	struct rb_node rb_node;

	unsigned free:1;
	unsigned allow_user_free:1;
	unsigned async_transcaction:1;
	unsigned debug_id:29;

	struct binder_transaction *transaction;

	struct binder_node *target_node;
	size_t data_size;
	size_t offset_size;
	uint8_t data[0];
};

(6) binder_proc 表示正在使用Binder机制的进程,能够保存调用Binder的各个进程或线程的信息,例如线程ID、进程ID、Binder状态信息等:

struct binder_proc {
	struct hlist_node proc_node;

	struct rb_root threads;
	struct rb_root nodes;
	struct rb_root refs_by_desc;
	struct rb_root refs_by_node;

	int pid;
	struct vm_area_struct *vma;
	struct files_struct *files;
	struct files_node deferred_work_node;
	int deferred_work;
	void *buffer;
	ptrdifff user_buffer_offset;
	//...

};

(7) binder_thread 用于存储每一个单独线程的信息:

struct binder_thread {
	struct binder_proc *proc;
	struct rb_node rb_node;
	int pid;
	int looper;
	struct binder_transaction *transaction_stack;
	struct list_head todo;
	uint32_t return_error;
	uint32_t return_error2;
	wait_queue_head_t wait;
	struct binder_stats stats;
};

struct binder_stats {
	int br[_IOC_NR(BR_FAILED_REPLY) + 1];
	int bc[_IOC_NR(BC_DEAD_BINDER_DONE) + 1];
	int obj_created[BINDER_STAT_COUNT];
	int obj_deleted[BINDER_STAT_COUNT];
}

(8) binder_transaction 中转请求和返回结果,并保存接收和要发送的进程信息。

(9) binder_write_read 在进程之间的通信过程中传输的数据,cmd域用于区分不同的请求

(10) BinderDriverCommandProtocol 该枚举中重要的是BC_TRANSACTION和BC_REPLY命令,

(11) BinderDriverReturnProtocol 定义了读操作命令协议

(12) binder_ptr_cookie和binder_transaction_data

(13) flat_binder_object 将在进程之间传递的数据称为Binder对象,用 flat_binder_object 表示


分析设备初始化

初始化函数 binder_init 如下:

static int __init binder_init(void) {
	int ret;
	binder_deferred_work_queue create_singlethread_workqueue("binder");

	if (!binder_deferred_work_queue) {
		return -ENOMEM;
	}
	binder_debugs_dir_entry_root = debugfs_create_dir("binder", NULL);
	if (binder_debugfs_dir_entry_root) 
		binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", binder_debugfs_dir_entry_root);
	ret = misc_register(&binder_miscdev);
	if (binder_debugfs_dir_entry_root) {
		debugfs_crate_file("state", S_IRUGO, binder_debugfs_dir_entry_root, NULL, &binder_state_fops);
		debugfs_crate_file("stats", S_IRUGO, binder_debugfs_dir_entry_root, NULL, &binder_stats_fops);
		debugfs_crate_file("transactions", S_IRUGO, binder_debugfs_dir_entry_root, NULL, &binder_transactions_fops);
		debugfs_crate_file("transaction_log", S_IRUGO, binder_debugfs_dir_entry_root, NULL, &binder_transaction_log_fops);
		debugfs_crate_file("failed_transaction_log", S_IRUGO, binder_debugfs_dir_entry_root, NULL, &binder_failed_transaction_log_fops);
	}
	return ret;
}

打开 Binder 设备文件

static int binder_open(struct inode *nodp, struct file *filp) {
	struct binder_proc *proc;
	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n", current->group_leader->pid, current->pid);
	proc = kzalloc(sizeof(*proc), GFP_KERNEL);
	if (proc == NULL) {
		return -ENOMEM;
	}
	get_task_struct(current);
	proc->tsk = current;
	INIT_LIST_HEAD(&proc->todo);
	init_waitqueue_head(&proc->wait);
	proc->default_priority = task_nice(current);
	binder_lock(__func__);
	binder_stats_created(BINDER_STAT_PROC);
	hlist_add_head(&proc->proc_node, &binder_procs);
	proc->pid = current->group_leader->pid;
	INIT_LIST_HEAD(&proc->delivered_death);
	filp->private_data = proc;
	binder_unlock(__func__);
	if (binder_debugs_dir_entry_proc) {
		char strbuf[11];
		snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
		proc->debugfs_entry = debugfs_create_file(strbuf, S_IRUGO, binder_debugfs_dir_entry_proc, proc, &binder_proc_fops);
	}
	return 0;
}

内存映射

打开 /dev/binder 后,需要调用函数mmap把设备内存映射到用户进程地址空间中。

static int binder_mmap(struct file *filp, struct vm_area_struct *vma) {
	int ret;
	struct vm_struct *area;
	struct binder_proc *proc = file->private_data;
	const char *failure_string;
	struct binder_buffer *buffer;

	// 内存范围小于4MB,则设置为4MB
	if ((vma->vm_end - vma->vm_start) > SZ_4M)
		vma->vm_end = vma->vm_start + SZ_4M;

	binder_debug(BINDER_DEBUG_OPEN_CLOSE,
				 "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n",
				 proc->pid, vma->vm_start, vma->vm_end,
				 (vma->vm_end - vm->vm_start) / SZ_1K, vma->vm_flags,
				 (unsigned long)pggrot_val(vma->vm_page_prot));

	if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
		ret = -EPERM;
		failure_string = "bad vm_flags";
		goto err_bad_arg;
	}
	vm->vm_flags = (vm->vm_flags | VM_DONTCOPY) & ~VM_MAYWRITE;

	mutex_lock(&binder_mmap_lock);

	if (proc->buffer) {
		ret = -EBUSY;
		failure_string = "already mmaped";
		goto err_alreadey_mapped;
	}

	area = get_vm_area(vma->vm_end - vm->vm_start, VM_IOREMAP);
	if (area == NULL) {
		ret = -ENOMEM;
		failure_string = "get_vm_area";
		goto err_get_vm_area_failed;
	}

	proc->buffer = area->addr;
	proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;

	mutex_unlock(&binder_mmap_lock);

#ifdef CONFIG_GPU_CACHE_VIPT
	if (cache_is_vipt_aliasing()) {
		while (CACHE_COLOUR(vma->vm_start ^ (uint32_t)proc->buffer)) {
			printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
			vma->vm_start += PAGE_SIZE;
		}
	}
#endif

	proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end) - vma->vm_start) / PAGE_SIZE, GFP_KERNEL);
	if (proc->pages == NULL) {
		ret = -ENOMEM;
		failure_string = "alloc page array";
		goto err_alloc_pages_failed;
	}
	proc->buffer_size = vma->vm_end - vma->vm_start;

	vma->vm_ops = &binder_vm_ops;
	vma->vm_private_data = proc;

	if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {
		ret = -ENOMEM;
		failure_string = "alloc small buf";
		goto err_alloc_small_buf_failed;
	}
	buffer = proc->buffer;
	INIT_LIST_HEAD(&proc->buffers);
	list_add(&buffer->entry, &proc->buffers);
	buffer->free = 1;
	binder_insert_free_buffer(proc, buffer);
	proc->free_async_space = proc->buffer_size / 2;
	barrier();
	proc->files = get_files_struct(proc->tsk);
	proc->vma = vma;
	proc->vma_vm_mm = vma->vm_mm;

	return 0;
}

err_alloc_small_buf_failed:
	kfree(proc->pages);
	proc->pages = NULL;

err_alloc_pages_failed:
	mutex_lock(&binder_mmap_lock);
	vfree(proc->buffer);
	proc->buffer = NULL;

err_get_vm_area_failed:
err_alreadey_mapped:
	mutex_unlock(&binder_mmap_lock);
err_bad_arg:
	printk(KERN_ERR "binder_mmap: %d %1x-%lx %s failed %d\n", proc->pid, vma->vm_start, vm->end, failure_string, ret);
	return ret;

VMA的功能是管理进程地址空间中不同区域的数据结构。

物理内存(page)的分配工作是通过函数 binder_update_page_range 实现的,主要完成以下工作:

static int binder_update_page_range(struct binder_proc *proc, int allocate, void *start, void *end, struct vm_area_struct *vma) {
	void *page_addr;
	unsigned long user_page_addr;
	struct vm_struct rmp_area;
	struct page **page;
	struct mm_struct *mm;

	binder_debug(BINDER_DEBUG_BUFFER_ALLOC, "binder: %d: %s pages %p-%p\n", proc->pid, allocate ? "allocate" : "free", start, end);

	if (end <= start) {
		return 0;
	}

	trace_binder_update_page_range(proc, allocate, start, end);

	mm = vma ? NULL : get_task_mm(proc->tsk);
	
	if (mm) {
		down_write(&mm->mmap_sem);
		vma = proc->vma;
		if (vma && mm != proc->vm_mm) {
			pr_err("binder: %d: vma mm and task mm mismatch\n", proc->pid);
			vma = NULL;
		}
	}

	if (allocate == 0) {
		goto free_range;
	}

	if (vma == NULL) {
		printk(KERN_ERR "binder: %d: binder_alloc_buf failed to map pages in userspace, no vma\n", proc->pid);
		goto err_no_vma;
	}

	for (page_add = start; page_addr < end; page_addr += PAGE_SIZE) {
		int ret;
		struct page **page_array_ptr;
		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];

		BUG_ON(*page);
		*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
		if (*page == NULL) {
			printk(KERN_ERR "binder: %d: binder_alloc_buf failed for page at %p\n", proc->pid, page_addr);
			goto err_alloc_pages_failed;
		}

		user_page_addr = (uintptr) page_addr + proc->user_buffer_offset;
		ret = vm_insert_page(vma, user_page_addr, page[0]);
		if (ret) {
			printk(KERN_ERR "binder: %d: binder_alloc_buf failed to map page at %lx in userspace\n", proc->pid, user_page_addr);
			goto err_vm_insert_page_failed;
		}
	}
	if (mm) {
		up_write(&mm->mmap_sem);
		mmput(mm);
	}
	return 0;
}

free_range:
	for (page_addr = end - PAGE_SIZE; page_addr >= start; page_addr -= PAGE_SIZE) {
		page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
		if (vma) {
			zap_page_range(vma, (uintptr_t)page_addr + proc->user_buffer_offset, PAGE_SIZE, NULL);
		}
	}

err_vm_insert_page_failed:
	unmap_kernel_range((unsigned long))page_addr, PAGE_SIZE;

err_map_kernel_failed:
	__free_page(*page);
	*page = NULL;

err_alloc_pages_failed:
	;

err_no_vma:
	if (mm) {
		up_write(&mm->mmap_sem);
		mmput(mm);
	}
	return -ENOMEM;

释放物理页面

函数 binder_insert_free_buffer 能将一个空闲内核缓冲区加入到进程中的空闲内核缓冲区的红黑树中:

static void binder_insert_free_buffer(struct binder_proc *proc, struct binder_buffer *new_buffer) {
	struct rb_node **p = &proc->free_buffers.rb_node;
	struct rb_node (parent) = NULL;
	struct binder_buffer = *buffer;
	size_t buffer_size;
	size_t new_buffer_size;
	BUG_ON(!new_buffer->free);
	new_buffer_size = binder_buffer_size(proc, new_buffer);
	binder_debug(BINDER_DEBUG_BUFFER_ALLOC, "binder: %d: add free buffer, size %zd, at %p\n", proc->pid, new_buffer_size, new_buffer);

	while (*p) {
		parent = *p;
		buffer = rb_entry(parent, struct binder_buffer, rb_node);
		BUG_ON(!buffer->free);
		buffer_size = binder_buffer_size(proc, buffer);
		if (new_buffer_size < buffer_size) {
			p = &parent->rb_left;
		} else {
			p = &parent->rb_right;
		}
	}
	rb_link_node(&new_buffer->rb_node, parent, p);
	rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);
}

分配内核缓冲区

Binder在使用buffer的时候,一次声明一个proc的buffer总大小,然后分配一页并做好映射,如果空间不足,会接着映射并把这个buffer拆成两个,并把剩余的继续放到free_buffers里面。

static struct binder_buffer* binder_alloc_buf(struct binder_proc *proc, size_t data_size, size_t offsets_size, int is_async) {
	struct rb_node *n = proc->free_buffers.rb_node;
	struct binder_buffer *buffer;
	size_t buffer_size;
	struct rb_node *best_fit = NULL;
	void *has_page_addr;
	void *has_page_addr;
	void *end_page_addr;
	size_t size;
	if (proc->vma == NULL) {
		printk(KERN_ERR "binder: %d: binder_alloc_buf, no vma\n", proc->pid);
		return NULL;
	}
	size = ALIGN(data_size, sizeof(void*)) + ALIGN(offsets_size, sizeof(void*));
	if (size < data_size || size < offsets_size) {
		binder_user_error("binder: %d: got transaction with invaild size %zd-%zd\n", proc->pid, data_size, offsets_size);
		return NULL;
	}
	if (is_async && proc->free_async_space < size + sizeof(struct binder_buffer)) {
		binder_debug(BINDER_DEBUG_BUFFER_ALLOC, "binder: %d: binder_alloc_buf size %zd failed, no async space left\n", proc->pid, size);
		return NULL;
	}
	// ...
}

函数binder_insert_allocated_buffer的功能是将分配的内核缓冲区添加到目标进程的已分配物理页面的内核缓冲区红黑树中:


释放内核缓冲区

函数 binder_free_buf 的功能是执行释放内核缓冲区的操作。

函数 buffer_start_page 和 buffer_end_page 用于计算结构体 binder_buffer 所占用的虚拟页面地址。

函数 buffer_delete_free_buffer 功能是删除结构体 binder_buffer


查询内存缓冲区

binder_buffer_look_up 的功能是根据一个用户空间地址查询一个内核缓冲区:

static struct binder_buffer* binder_buffer_look(struct binder_proc *proc, void __user *user_ptr) {
	struct rb_node *n = proc->allocated_buffers.rb_node;
	struct binder_buffer *buffer;
	struct binder_buffer *kern_ptr;
	kern_ptr = user_ptr - proc->user_buffer_offset - offsetof(struct binder_buffer, data);

	while (n) {
		buffer = rb_entry(n, struct binder_buffer, rb_node) {
			BUG_ON(buffer->free);

			if (kern_ptr < buffer) {
				n = n->rb_left;
			} else if (kern_ptr > buffer) {
				n = n->rb_right;
			} else {
				return buffer;
			}
		}
		return NULL;
	}
}

5.3 Binder封装库

5.3.1 Binder库的实现层次

(1) Binder驱动部分 (2) Binder Adapter层 (3) 顶层

5.3.2 类BBinder

BBinder是服务的载体,与Binder驱动共同工作,保证客户的请求最终是对一个Binder对象(BBinder)的调用。

5.3.3 BpRefBase

BpRefBase以上是业务逻辑(要实现什么功能),以下是数据传输(通过Binder如何将功能实现),在文件 frameworks/native/include/binder/Binder.h

5.3.4 类IPCThreadState

BBinder和BpRefBase都是通过IPCThreadState和Binder的驱动程序交互实现的,IPCThreadState在文件 frameworks/native/include/binder/IPCThreadState.h中实现。

5.4 初始化Java层Binder框架

函数 register_android_os_Binder 专门负责搭建 Java Binder 和 Native Binder 的交互关系,在 frameworks/base/core/jni/android_util_Binder.cpp 中实现:

int register_android_os_Binder(JNIEnv *env) {
	// 初始化Java Binder类和Native层的关系
	if (int_register_android_os_Binder(env) < 0) {
		return -1;
	}
	// 初始化Java BinderInternal类和Native层的关系
	if (int_register_android_os_BinderInternal(env) < 0) {
		return -1;
	}
	// 初始化Java BinderProxy类和Native层的关系
	if (int_register_android_os_BinderProxy(env) < 0) {
		return -1;
	}
	// 初始化Java Parcel类和Native层的关系
	if (int_register_android_os_Parcel(env) < 0) {
		return -1;
	}
	return 0;
}

同时代码中定义了几个全局静态对象,分别是gBinderOffsets、gBinderInternalOffsets和gBinderProxyOffsets

6 Zygote进程详解

Zygote的父进程是init,而它是system_server和所有应用的父进程,为启动Java代码而生,完成一次androidRuntime的打开和关闭操作,Zygote即JVM。

6.1 分析Zygote的启动过程

system/core/rootdir/init.rc 中可以看到启动Zygote进程的脚本:

servicezygote/system/bin/app_process-Xzygote/system/bin--zygote--start-system-server socket zygote stream 666

通过上述代码,系统启动后会在/dev/socket目录下看到一个名为zygote的文件,

(1) 分析启动脚本 在文件 system/core/init/init.c 中,以服务的形式来启动Zygote进程。

void service_start(struct service *svc, const char *dynamic_args) {
	struct stat s;
	pid_t pid;
	int needs_console;
	int n;
	char *scon = NULL;
	int rc;

	svc->flags &= (~(SVC_DISABLED | SVC_RESTARTING | SVC_RESET));
	svc->time_started = 0;

	if (svc->flags & SVC_RUNNING) {
		return;
	}

	needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
	if (needs_console && (!have_console)) {
		ERROR("service '%s' requires console\n", svc->name);
		svc->flags |= SVC_DISABLED;
		return;
	}

	if (stat(svc->args[0], &s) != 0) {
		ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
		svc->flags |= SVC_DISABLED;
		return;
	}

	if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
		ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]);
		svc->flags |= SVC_DISABLED;
		return;
	}
	//...
}

(2) 分析入口函数

(3) 分析启动函数

(4) 与Zygote进程中的Socket实现连接

6.2 System进程详解

通过Zygote的成员函数handleSystemServerProcess来启动System进程。

6.2.1 启动 System 进程前的准备工作

(1) 获取Socket,见 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

private static void handleSystemServerProcess(
	ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller{
	closeServerSocket();

	Libcore.os.umask(S_IRWXG | S_IRWXO);
	if (parsedArgs.niceName != null) {
		Process.setArgVO(parsedArgs.niceName);
	}
	if (parsedArgs.invokeWith != null) {
		WarpperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, null, parsedArgs.remainingArgs);
	} else {
		RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
	}
}

(2) 启动System进程

public static final void zygoteInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller {
	if (DEBUG) {
		Slog.d(TAG, "RuntimeInit: Starting application from zygote");
	}
	redirectLogStreams();
	commonInit();
	nativeZygoteInit();
	applicationInit(targetSdkVersion, argv);
}

6.2.2 分析 SystemServer

frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {
	if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
		Slog.w(TAG, "System clock is before 1970; setting to 1970.");
		SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
	}

	if (SamplingProfilerIntegration.isEnabled()) {
		SamplingProfilerIntegration.start();
		timer = new Timer();
		timer.schedule(new TimerTask(){
			@Override
			public void run() {
				SamplingProfilerIntegration.writeSnapshot("system_server", null);
			}
		}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
	}

	dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();

	VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
	System.loadLibrary("android_servers");
	init1(args);
}

public static final void init2() {
	Slog.i(TAG, "Entered the Android system server!");
	Thread thr = new ServerThread();
	thr.setName("android.server.ServerThread");
	thr.start();
}

ServerThread 的 run 方法包含七大类43个Service:

6.3 应用程序进程

6.3.1 创建应用程序

ActivityManagerService中的startProcessLocked向孵化进程Zygote发送创建应用进程的请求,见 frameworks/base/services/java/com/androids/server/am/ActivityManagerService.java

private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) {
	if (app.pid > 0 && app.pid != MY_PID) {
		synchronized(mPidsSelfLocked) {
			mPidsSelfLocked.remove(app.pid);
			mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
		}
		app.setPid(0);
	}

	if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) {
		Slog.v(TAG, "startProcessLocked removing on hold: " + app);
	}
	mProcessOnHold.remove(app);

	updateCpuStats();
	System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length - 1);

	mProcDeaths[0] = 0;
	try {
		int uid = app.uid;
		int[] gids = null;
		int mountExternal = Zygote.MOUNT_EXTERNAL_NOTE;
		if (!app.isolated) {
			int[] permGids = null;
			try {
				final PackageManager pm = mContext.getPackageManager();
				permGids = pm.getPackageGids(app.info.packageName);

				if (Environment.isExternalStorageEmulated()) {
					if (pm.checkPermission(android.Mainfest.permission.ACCESS_ALL_EXTERNAL_STORAGE, 
						app.info.packageName) == PERMISSION_GRANTED) {
						mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
					} else {
						mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
					}
				}
			} catch(PackageManager.NameNotFoundException e) {
				Slog.w(TAG, "Unable to retrieve gids", e);
			}
			// ...

		}
	}
	// ...
}

6.3.2 启动线程池

调用类RuntimeInit中的函数nativeZygoteInit启动一个新的Binder线程池

6.3.3 创建信息循环

调用invokeStaticMain,将类ActivityThread的main方法设置成新程序的入口,当使用main方法时,会在当前程序的进程中建立一个信息循环

private static void invokeStaticMain(String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller {
	Class<?> cl;

	try {
		cl = Class.forName(className);
	} catch (ClassNotFoundException ex) {
		throw new RuntimeException("Missing class when invoking static main " + className, ex);
	}

	Method m;
	try {
		m = cl.getMethod("main", new Class[]{String[].class});
	} catch(Exception e){

	}

	int modifiers = m.getModifiers();
	if(!(Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
		// throw
	}

	// 通过抛出异常的方式,让其被main方法捕获
	throw new ZygoteInit.MethodAndArgsCaller(m, args);
}

7 Activity基础

7.1 Activity基础

7.1.1 的状态

7.1.2 Activity的主要方法

假设某个程序由两个Activity A(启动界面)和B组成。

动作 呈现界面 Task栈 被调用的方法
用户启动程序 A界面 A A{onCreate, onStart, onResume}
用户在A中开启B B界面 B,A A{onPause}, B{onCreate, onStart, onResume}
在B上按Back键回到A A界面 A B{onPause, onStop, onDestory}, A{onResume}
突然来电 电话接听界面 A界面 A{onPause}
按Home键回到桌面,打开联系人程序 联系人程序界面 A A{Stop}
重新点击程序进入 A界面 A A{onRestart, onStart, onResume}
按Back键返回桌面 桌面 A{onPause, onStop, onDestory}

7.2 启动 Activity

ActivityManagerService 负责启动Activity,管理Activity的生命周期,通过ActivityStack将所有的Activity按照后进先出的顺序放在一个栈中;每个应用程序,都有一个专门的ActivityThread来表示其主进程,其包含一个Binder类型的ApplicationThread实例,其功能是与其他进程实现通信。

启动Activity的流程: (1) 通过 Binder 进程间通信进入到ActivityManagerService进程中,并且将会调用ActivityManagerService.startActivity接口 (2) ActivityManagerService调用ActivtyStack.startActivityMayWait,做好启动Activity前的准备 (3) ActivityStack通知ApplicationThread即将启动Activity,