Android输入事件读入流程
来源:互联网 发布:球体运动js效果大全 编辑:程序博客网 时间:2024/05/29 15:39
一.从SystemService.java中启动服务
代码路径:frameworks/base/services/java/com/android/server/SystemServer.java
public class SystemServer
{
.....
native public static void init1(String[] args);
public static void main(String[] args) {
.........
init1(args);
}
public static final void init2() {
Slog.i("yaojuntaoSystemServer", "Entered the Android system server!");
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
}
调用init1(args),初始化显示系统,音频等,init1通过JNI调用到com_android_server_SystemServer.cpp
的static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz),而android_server_SystemServer_init1会调用system_init();
system_init()将调用在 System_init.cpp 中
extern "C" status_t system_init()
{
......
runtime->callStatic("com/android/server/SystemServer",
SystemService.java 中的 init2。
......
}
在init2中会建立一个服务线程,我们可以看一下:
class ServerThread extends Thread {
...
public void run()
{
...
wm = WindowManagerService.main(context, power,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
((ActivityManagerService)ServiceManager.getService("activity"))
.setWindowManager(wm);
...
}
}
在这个线程中调用了很多的service,我们主要关注的是WindowMangerService接下来跳转到WindowMangerService分析。
二.WindowMangerService
代码路径:services/java/com/android/server/WindowManagerService.java
由SystemService.java调到WindowManagerService 的main方法:
public static WindowManagerService main(Context context,
PowerManagerService pm, boolean haveInputMethods) {
WMThread thr = new WMThread(context, pm, haveInputMethods);
thr.start();
Slog.e("yaojuntaoWindowManagerService","WindowManagerService thr ok");
synchronized (thr) {
while (thr.mService == null) {
try {
thr.wait();
} catch (InterruptedException e) {
}
}
}
return thr.mService;
}
在main中建立了线程:
static class WMThread extends Thread {
..
public void run() {
...
WindowManagerService s = new WindowManagerService(mContext, mPM,
mHaveInputMethods);
...
}
建立了 WindowManagerService的对象,将跳到构造函数:
private WindowManagerService(Context context, PowerManagerService pm,
boolean haveInputMethods) {
........
int max_events_per_sec = 35;
try {
max_events_per_sec = Integer.parseInt(SystemProperties
.get("windowsmgr.max_events_per_sec"));
if (max_events_per_sec < 1) {
max_events_per_sec = 35;
}
} catch (NumberFormatException e) {
}
mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
private WindowManagerService(Context context, PowerManagerService pm,
boolean haveInputMethods) {
mQueue = new KeyQ();
mInputThread = new InputDispatcherThread();
PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
thr.start();
.........
}
在该段代码中我们看到mQueue = new KeyQ(),该句建立了输入的队列,通过这个去读底部传上来的数据,我们暂时不向下看,在mInputThread = new InputDispatcherThread()一句中建立了数据的分发线程,我们来看一下:
private final class InputDispatcherThread extends Thread {
......
public void run() {
while (true) {
try {
process();
} catch (Exception e) {
Slog.e(TAG, "Exception in input dispatcher", e);
}
}
}
....
}
调用了 process(),好,继续看 process():
private void process() {
....
while (true) {
....
QueuedEvent ev = mQueue.getEvent(
(int)((!configChanged && curTime < nextKeyTime)
? (nextKeyTime-curTime) : 0));
......
}
}
我们看到在process()中进入了循环,在循环中调用mQueue.getEvent从queue中获得数据并分发,mQueue这个对象在上面建立的,我们会看到这个对象的方法与属性,在此我们可以看到输入的上层的流程,紧接着向下走。
三.KeyInputQueue.java
代码:services/java/com/android/server/KeyInputQueue.java
在上次提到mQueue = new KeyQ();这行,而在WindowMangerService中有:
private class KeyQ extends KeyInputQueue,然后我们找到 KeyInputQueue的构造函数:
KeyInputQueue(Context context, HapticFeedbackCallback hapticFeedbackCallback) {
.....
mThread.start();
....
}
我们看一下mThread这个线程:
Thread mThread = new Thread("InputDeviceReader") {
public void run() {
...
while (true) {
try {
InputDevice di;
// block, doesn't release the monitor
readEvent(ev);
....
}
}
}}
可以看到在该线程中循环通过readEvent(ev)去读事件,而private static native boolean readEvent(RawInputEvent outEvent)说明调用为JNI中的函数,另为我们发现QueuedEvent getEvent(long timeoutMS) 方法被调用时,值传了上去。
四.JNI
代码:
services/jni/com_android_server_KeyInputQueue.cpp
在com_android_server_KeyInputQueue.cpp中我们发现了:
static jboolean
android_server_KeyInputQueue_readEvent(JNIEnv* env, jobject clazz,
jobject event)
{
....
bool res = hub->getEvent(&deviceId, &type, &scancode, &keycode,
&flags, &value, &when);
.....
}
我们来看hub->getEven,代码路径在libs/ui/EventHub.cpp
bool EventHub::getEvent(int32_t* outDeviceId, int32_t* outType,
int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
int32_t* outValue, nsecs_t* outWhen)
{
....
if (!mOpened) {
mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;
mOpened = true;
}
......
}
penPlatformInput()将扫描/dev/input 下的所有 event 并打开它
bool EventHub::openPlatformInput(void)
{
......
res = scan_dir(device_path);//其中 static const char *device_path = "/dev/input";
......
}
而
int EventHub::scan_dir(const char *dirname)
{
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
dir = opendir(dirname);
if(dir == NULL)
return -1;
strcpy(devname, dirname);
filename = devname + strlen(devname);
*filename++ = '/';
//扫描/dev/input 下的所有 event 并打开它
while((de = readdir(dir))) {
if(de->d_name[0] == '.' &&
(de->d_name[1] == '/0' ||
(de->d_name[1] == '.' && de->d_name[2] == '/0')))
continue;
strcpy(filename, de->d_name);
open_device(devname);//打开 event 设备
}
closedir(dir);
return 0;
}
int EventHub::open_device(const char *deviceName)
{
......
fd = open(deviceName, O_RDWR);
......
}
如果上面的操作都成功则把所有设备都打开了,现回到 EventHub::getEvent。
release_wake_lock(WAKE_LOCK_ID);
pollres = poll(mFDs, mFDCount, -1);
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
在这边 poll,如果没有新事件将在这等待,如果有则开始下面的读事件
res = read(mFDs[i].fd, &iev, sizeof(iev));
到此整个从上面开始的读过程结束。
到此Android的输入流程已结束,接下来会详细刨析输入的细节。
- Android输入事件读入流程
- Android输入事件流程
- Android输入事件流程
- Android输入事件流程
- Android 输入事件流程
- Android输入事件流程
- Android 输入事件流程
- Android输入事件流程
- Android 输入事件流程
- Android输入事件流程 收藏
- Android事件处理分析+Android事件处理 +Android输入事件流程
- Android事件处理分析+Android事件处理 +Android输入事件流程
- Android输入事件流程中的EventHub分析及源码演示
- Android输入事件流程中的EventHub分析及源码演示
- Android输入事件流程中的EventHub分析及源码演示
- Android输入事件流程中的EventHub分析及源码演示
- Android处理输入事件的流程(一)
- android源码分析——事件输入流程MotionEvent事件处理流程
- 学习SilverLight(五)
- 非常实用的j avascript 验证码生成
- Linux slab 分配器剖析
- 如何在eclipse中自动添加注释
- VIM中自动添加注释信息
- Android输入事件读入流程
- 透视3G市场纷争 份额仍是悬念
- 【2011.4.28】GE面试总结
- eclipse(MyEclipse)关闭鼠标移动提示代码功能和自定义快捷键代码提示设置的...
- Creating your first Windows Phone (WM 6.5) application
- Makefile指定编译选项
- eclipse 中的注释 快捷键
- ARP 欺骗
- 人人网移动开发架构