Android Input Event Dispatching

 

 

 

[First written by Steve Guo, please keep the mark if forwarding.]

Input Event Detect and Dispatch

The input event dispatch engine is in WindowManagerService.java. WindowManagerService.java creates a thread to read input event from KeyInputQueue.java and dispatches the event to the window which has current focus through binder.

                // Retrieve next event, waiting only as long as the next

                // repeat timeout.  If the configuration has changed, then

                // don't wait at all -- we'll report the change as soon as

                // we have processed all events.

                QueuedEvent ev = mQueue.getEvent(

                    (int)((!configChanged && curTime < nextKeyTime)

                            ? (nextKeyTime-curTime) : 0));

If an input event is read, it judges the input event type. Currently support three input event types: key, trackball and pointer. Then according to event type call corresponding dispatch function to the window which has current focus through binder. For example, for key event, it calls the following code.

            focus.mClient.dispatchKey(event);

At the lowest level, Android reads the real input event (keyboard, mouse or touch) from Linux input device. The corresponding source code is EventHub.cpp. For key input event, Android maps scan code to key code according to a key layout map file. OEM needs customize the key layout map file to match the needs of his own device. It uses the following method to find out the key layout map file.

        // a more descriptive name

        ioctl(mFDs[mFDCount].fd, EVIOCGNAME(sizeof(devname)-1), devname);

        devname[sizeof(devname)-1] = 0;

        device->name = devname;

 

        // replace all the spaces with underscores

        strcpy(tmpfn, devname);

        for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))

            *p = '_';

 

        // find the .kl file we need for this device

        const char* root = getenv("ANDROID_ROOT");

        snprintf(keylayoutFilename, sizeof(keylayoutFilename),

                 "%s/usr/keylayout/%s.kl", root, tmpfn);

        bool defaultKeymap = false;

        if (access(keylayoutFilename, R_OK)) {

            snprintf(keylayoutFilename, sizeof(keylayoutFilename),

                     "%s/usr/keylayout/%s", root, "qwerty.kl");

            defaultKeymap = true;

        }

        device->layoutMap->load(keylayoutFilename);

OEM can get the key layout map file name during Android booting, because Android will log the name. The JAVA layer wrapper is KeyInputQueue.java which is used by WindowManagerService.java. It calls EventHub.cpp through JNI. com_android_server_KeyInputQueue.cpp is the JNI implementation.

 

Input Event Processing

When an activity is to be launched, ActivityManagerService.java calls ActivityThread.java for creating the activity.

                activity.attach(appContext, this, getInstrumentation(), r.token, app,

                        r.intent, r.activityInfo, title, r.parent, r.embeddedID,

                        r.lastNonConfigurationInstance, config);

Then Activity.java creates a PhoneWindow.java instance to represent the activity. Each PhoneWindow.java contains a DecorView.java instance as the root of any views in the activity.

        mWindow = PolicyManager.makeNewWindow(this);

        mWindow.setCallback(this);

After an activity is created, ActivityManagerService.java calls ActivityThread.java for resume the activity. At this time, ActivityThread.java calls WindowManagerImpl.java to add the DecorView.java instance.

                r.window = r.activity.getWindow();

                View decor = r.window.getDecorView();

                decor.setVisibility(View.INVISIBLE);

                ViewManager wm = a.getWindowManager();

                WindowManager.LayoutParams l = r.window.getAttributes();

                a.mDecor = decor;

                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;

                wm.addView(decor, l);

WindowManagerImpl.java news a ViewRoot.java instance. ViewRoot.java has a static member which will be only initialized once for each process. It’s used to let WindowManagerService.java know that there is a process linked now.

            if (!mInitialized) {

                try {

                    sWindowSession = IWindowManager.Stub.asInterface(

                            ServiceManager.getService("window"))

                            .openSession(new Binder());

                    mInitialized = true;

                } catch (RemoteException e) {

                }

            }

After ViewRoot.java instance is created, WindowManagerImpl.java calls its setView API to bind the ViewRoot.java for the DecorView.java.

        // do this last because it fires off messages to start doing things

        root.setView(view, wparams, panelParentView);

In setView API, ViewRoot.java finally draws the DecorView.java and registers an IWindow instance to WindowManagerService.java.

                    res = sWindowSession.add(mWindow, attrs,

                            getHostVisibility(), mCoveredInsets);

After that WindowManagerService.java directly communicates (including dispatching input event) with this IWindow instance in ViewRoot.java. Then ViewRoot.java calls View.java to process input event. For example, for key event, dispatchKeyEvent API in View.java will be called.

    public boolean dispatchKeyEvent(KeyEvent event) {

        // If any attached key listener a first crack at the event.

        //noinspection SimplifiableIfStatement

        if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED

                && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {

            return true;

        }

   

        return event.dispatch(this);

    }

View.java detects if any key listener is registered for this view. If so, the key event will be handled by the key listener. Otherwise, it calls OnKeyDown/OnKeyUp as usual.

 

All the key listener implementations are under frameworks/base/core/java/android/text/method folder.

MultiTapKeyListener.java       - if the keypad is NUMERIC keypad, this listener is used to transform digit inputs to characters.

QwertyKeyListener.java – if the keypad is QWERTY keypad, this listener is used.

 

 

 

 

 原文地址 http://letsgoustc.spaces.live.com/blog/cns!89AD27DFB5E249BA!488.entry?_c=BlogPart

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值