Android 核心入门分析 Jack.fan Copyright 2007-2008 Farsight. All rights reserved.
主要内容 : } 1 android 系统启动流程分析 } 2 android 系统 JNI 和 Binder 使用简介 } 3 android 系统输入子系统模型分析
1.1 android 系统启动流程分析 : } 1). } init 进程启动控制台进程 } init 进程启动 servicemanager 进程 ( 即 runtime 进程 ) } => 打开 /dev/binder 等, 并设置自己为 runtime(context), 用于对系统中的所有服务进行统一管理 } init 进程启动 vold/debuggerd/rild 进程 } 2). } init 进程启动 Zygote 进程
1.2 android 系统启动流程分析 : } 3). } runtime 进程请求 Zygote 启动 SystemServer 进程 } 4). } SystemServer 进程启动两个本地服务 : SurfaceFlinger/AudioFlinger } SurfaceFlinger/AudioFlinger 向 ServiceManager 注册 } 5). } SystemServer 进程启动其他 Android 服务 ( 如 WindowManager) } 所有的 Android 服务向 ServiceManager 注册
1.3 android 系统启动流程分析 : } android_src/system/core/init.c } parse_config_file("/init.rc") } snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware) } parse_config_file(tmp) } action_for_each_trigger("init", action_add_queue_tail) // 运行脚本文件中的 on init 段 } action_for_each_trigger("early-boot", action_add_queue_tail); } action_for_each_trigger("boot", action_add_queue_tail);
1.4 android 系统启动流程分析 : } init.rc } service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server } frameworks/base/cmds/app_process/app_main.cpp } main() } Step 1 => 解析虚拟机的运行参数 } Step 2 => 解析 dexopt 运行参数 } Step 3 => 初始化 VM 虚拟机 (Initialize the VM) : 这里启 动虚拟机后, 这以后就可以运行 java 代码了 } Step 4 => 初始化 JNI 模块 ( 注册 android 函数 ) : 这以 后,CPP 和 JAVA 代码之间就可以互相函数调用了 } Step 5 => 启动 VM 虚拟机 (Start VM. This thread becomes the main thread of the VM, and will not return until the VM exits)
1.5 android 系统启动流程分析 : } Step 6 => 启动进程 system_server => 该进程会启 动 android 的后续全部进程 } Step 7 => 启动 SurfaceFlinger 和 AudioFlinger } 打开 /dev/pmem 设备 : } 开始 android 机器人开机动画的显示 : } Step 8 => 启动其他的各种服务并将这些服务添加到 ServiceManager 中 : 如 PowerManager,ActivityManager,WindowManager,InputMet hodmanagerservice,... } 这里将启动 android 系统上电后用户看到的第一个锁屏显示界 面 (HomeApp) => 最后 SystemServer::init2 将会调用 ActivityManagerService.systemReady 通过发送 Intent.CATEGORY_HOME intent 来启动第一个 activity 然后开始等待新的 android 应用启动请求 ( 提供 fork() 服务 )
1.6 android 系统启动流程分析 :
1.7 android 系统启动流程分析 :
2.1 android 系统 JNI 和 Binder 使用简介 : } 用于 Java 代码和本地代码 (C/C++) 的互相调用
2.2 android 系统 JNI 和 Binder 使用简介 : } android java 调用 CPP 函数 : 原理 => 相当于 java 的那个 class 里面有的函数使用 CPP 代码来实现了 } 1) 通过结构 JNINativeMethod 描述 java 代码调用函数和 CPP 函数的对应关系 : } typedef struct { } const char* name; // java 代码调用 CPP 函数的入口 } const char* signature; // CPP 函数的返回值 } void* fnptr; // CPP 的函数名 } } JNINativeMethod;
2.3 android 系统 JNI 和 Binder 使用简介 : } => 例如 : java 代码通过 IBinder.transact() 来调用 CPP 的函数 android_os_binderproxy_transact() } {"transact", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_binderproxy_transact}, } 2) 将 CPP 函数注册到 java 的某个 class 中 : 使用函数 AndroidRuntime::registerNativeMethods() 来注册 } => 这之后,java 代码就可以调用 CPP 函数了 } 3)java 代码调用 CPP 函数方法 : } IBinder.transact()
2.4 android 系统 JNI 和 Binder 使用简介 : } andorid CPP 调用 java 函数 : 原理 => 相当于 CPP 代码找到 java 的那个 class 里面的函数的入口地址, 然后在 CPP 代码中调用 java 代码 } 1) 通过结构 JNINativeInterface 描述 CPP 代码调用 java 函数的对应关系 : } CallStaticVoidMethod
2.5 android 系统 JNI 和 Binder 使用简介 : } 2) 到 java 的那个 class( 如 android.os.binder) 中找到 java 函数 ( 如 exectransact()) 的入口 : } jclass clazz = env->findclass(kbinderpathname) // const char* const kbinderpathname = "android/os/binder"; } gbinderoffsets.mexectransact = env->getmethodid(clazz, "exectransact", "(IIII)Z") } 3) 在 CPP 代码中调用 java 函数 : } env->callbooleanmethod(mobject, gbinderoffsets.mexectransact, code, (int32_t)&data, (int32_t)reply, flags
3.1 android 输入子系统模型分析 : } Step 1 => WindowManagerService 运行线程 InputDeviceReader 用于读取如下消息 : 按键消息, 触摸屏消息, 轨迹球消息 } Step 2 => WindowManagerService 运行线程 PolicyThread : 结合 PhoneWindowManager.java/KeyguardViewMediator.java 来管理当前窗口显示等 } Step 3 => WindowManagerService 运行线程 InputDispatcherThread : 将线程 InputDeviceReader() 放在事件队列里面的消息分发出去
3.2 android 输入子系统模型分析 : } InputDeviceReader() 运行流程 : } Step 1: 调用底层函数, 从 /dev/input/ 下面的输入设备读入输入事件 } Step 2: 对读入的输入事件作预处理 -> 用于决定是否要分发给系统的其他模块 ( 不分发的输入事件要么自己处理, 要么丢弃, 这需要让 PhoneWindowManager 来决定 ) } Step 3: 将读入的输入事件放到各自对应的事件队列中
3.3 android 输入子系统模型分析 : } 寻找 kl 文件的原理如下 : } 1) 首先寻找 /system/usr/keylayout/gpio-keys.kl => I/EventHub( 698): New keyboard: publicid=65537 device- >id=65537 devname='gpio-keys' propname='hw.keyboards.65537.devname' keylayout='/system/usr/keylayout/qwerty.kl' } 2) 如果没有, 就默认使用 /system/usr/keylayout/qwerty.kl
3.4 android 输入子系统模型分析 : } 从驱动读取到输入事件的信息 : } 然后将 CPP 层读取到的输入事件写入 java 层代码中 : } env->setintfield(event, ginputoffsets.mdeviceid, (jint)deviceid); } env->setintfield(event, ginputoffsets.mtype, (jint)type); } env->setintfield(event, ginputoffsets.mscancode, (jint)scancode); } env->setintfield(event, ginputoffsets.mkeycode, (jint)keycode); } env->setintfield(event, ginputoffsets.mflags, (jint)flags); } env->setintfield(event, ginputoffsets.mvalue, value);
www.farsight.com.cn Thanks!