'프레임워크'에 해당되는 글 3건

  1. 2010.01.07 안드로이드 event dispatch 과정 (1)
  2. 2008.07.15 프레임워크 스터디 1차 모임 (2)
  3. 2008.07.15 프레임워크(Framework)란?

출처 : http://blog.naver.com/osk1004?Redirect=Log&logNo=50069078782


==========================================================================================

원문 : http://letsgoustc.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&_c=BlogPart&partqs=amonth%3d12%26ayear%3d2008

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

Input Event Detect and Dispatch

input event dispatch engine 은 WindowManagerService.java 안에 위치한다.

WindowManagerService.java 는 KeyInputQueuq.java 로 부터 input event 를 read 하기 위한 하나의 thread 를 생성한다.

그리고, 그 event 를 binder 를 통해서 현재 focus 가 있는 window 로 dispatch 시키는 일을 한다.

                // 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));

input event 가 읽어 지면,  input event type 을 결정한다.현재는 3개의 input event type 을 지원한다.

1. Key

2. Trackball

3. Pointer

binder 를 통해 현재 fucus 를 가지고 있는 window 로 event type 에 매핑되는 dispatch fucntion 을 호출한다.(아~ 해석이 어색하다)

 

key event 를 예를 들면, 아래의 code 를 호출하게 된다.

            focus.mClient.dispatchKey(event); 

 

가장 아랫단에서,  Android 는 Linux input device 로 부터 실제 input event(keyboard,mouse,touch 등)를 읽어들인다.

그에 상응하는 소스는 EventHub,cpp 이다.

Key input event 를 위해서, Android 는 key lyout map file로 부터 key code 를 scen 한다.

OEM 회사들은 필요하다면, 그들의 device 에 match 시키기 위해 key lay map file 을 customize 할 필요가 있다.

그것은 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 은 Android가 booting 하는 동안, key layout map file 이름을 가져올수 있다. 왜냐하면, Android 는 그 file name 을 기록할것이기 때문이다.

Java layer 단의 wrapper 는 WindowManagerService.java 에서 사용되어지는  KeyInputQueue.java 파일이다.

그것은 JNI 를 통해 EventHub.cpp 를 호출한다. com_android_server_KeyInputQueuq.cpp 는 JNI implementation 파일이다.

 

Input Event Processing

ativity 가 launch 되어질때, ActivityManagerService.java 는 activity 를 생성하기 위해서 ActivityThread.java 를 호출한다.

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

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

                        r.lastNonConfigurationInstance, config);

 

그러고 나서 Activity.java 가 activity 를 표시하기 위해 PhoneWindow.java 의 intance 를 생성한다. 각각의 PhoneWindow.java 는 activity 내의 view 들에 대한 Root 로써 DecorView.java 의 instance 를 포함하고 있다.

        mWindow = PolicyManager.makeNewWindow(this);

        mWindow.setCallback(this);

 

Activity 가 생성된 후에, Activity 를 resume 시키기 위해 ActivityManagerService.java 는 ActivityThread.java 를 호출한다.

이때, ActivityThread.java 는 DecorView.java 의 instance 를 add 시키기 위해서 WindowManagerImpl.java 를 호출한다.

                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 는 ViewRoot.java 의 instance 를 생성한다. ViewRoot.java 는 각각의 process 에서 오직 한번만 initialize 되는 static member 를 가진다.

그것은 WindowManagerService.java 에게 현재 link 된 process 가 있는지 여부를 알려줄때 사용되어진다.

            if (!mInitialized) {

                try {

                    sWindowSession = IWindowManager.Stub.asInterface(

                            ServiceManager.getService("window"))

                            .openSession(new Binder());

                    mInitialized = true;

                } catch (RemoteException e) {

                }

            }

 

ViewRoot.java instance 가 생성된 이후에, WindowManagerImpl.java 는 ViewRoot.java 를 binding 하기 위해 DecorView.java 에 대해 setView API 를 호출한다.

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

        root.setView(view, wparams, panelParentView);

 

setView API 안에서, 마침내 ViewRoot.java 는 DecorView.java 를 그리게 된다. 그리고 IWindow instance 를 WindowManagerService.java 에 register 시킨다.  

                    res = sWindowSession.add(mWindow, attrs,

                            getHostVisibility(), mCoveredInsets);

 

그이후에, WindowManagerService.java 는 ViewRoot.java 내에서 이 IWindow instance 와 직접적으로 통신한다.( Dispatching input event 를 포함해서...)

그러면, ViewRoot.java 는 input event 를 처리하기 위해서 View.java 를 호출한다.

Key event 를 예를 들면, View.java 안에 있는 dispatchKeyEvent() API 가 호출될 것이다.

    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);

    }

 

만약 어떤 Key listener 가 이 view 에 register 되어져 있다면, View.java 는 그것을 찾는다.

Key listener 가 있다면, 그 key event 는 그 Key listener 에 의해 처리되어질 것이다.

그렇지 않으면,  대개 OnKeyDown/OnKeyUp 을 호출하게 된다.

 

모든 Key listener 구현은 frameworks/base/core/java/android/text/metod 에 있다.

 

MultiTapKeyListener.java     -    keypad 가 NUMERIC 면, 이 listener 는 숫자입력을 문자로 변환할것이다.

QwertyKeyListener.java        -     keypad 가 QWERTY 면, 이 listener 가 사용된다.

 

 

 

=============================================== 원 문 ===============================================

[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.

Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요

  1. BlogIcon rolex replica 2013.01.22 16:57  댓글주소  수정/삭제  댓글쓰기

    팁 주셔서 감사합니다, 아마도이 호리 호리한 내 순수 지성의 인식 작용 마케팅을 사용할 수 있습니다 그리고 상호 작용을 시도에 어떠한 인종의 미디어를 사용하고 있으며 사람들이 유효 그린 저에 큰 친근합니다.

모임 시간

2008.07.12 12:00~14:30


모임 장소

서울시립대학교 IT관 3층 전산실


참석인원

박종욱, 허완, 박상현, 김광용


스터디 내용

Web Programmer 2.0 스터디에서 공부할 내용 개괄적 공유 - 링크

프로젝트 소개 - 링크

Struts2(Webwork)를 사용해서 Hello World 웹페이지에 출력하기 - 링크


스터디 과제

개발환경 세팅 - APM, Tomcat, Eclipse

Struts2를 사용해서 Hello World 를 출력하라

Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요

과연 프레임워크란 무엇인가?


개발에 대한 방법론을 강제하는 것이라 말 할 수 있겠다.


프레임워크를 사용하다보면 매우 답답한 느낌이 들때가 있다.


자유롭게 설계하고 코딩하는 것이 아니라 프레임워크가 제공 하는 가이드 대로 설계하고 코딩을 하게 된다.


하지만 바로 이런 점이 프레임워크가 가지는 강력한 힘이다.


현재 웹프로그래밍의 추세는 엄청난 규모의 프로젝트가 많다.


클라이언트 애플리케이션을 웹으로 옮기려는 시도는 끊이지 않고 있다.


그렇게 거대하고 복잡도가 높은 프로젝트를 하기 위해서 많은 사람들이 필요하게 되고


그 개발자들이 통일성 있게 빠르고 안정적으로 개발하기 위해 프레임워크란 매우 좋은 성과를 내고 있다.


생산성 향상에도 한 몫을 하고 있다. 중복되고 뒷단을 처리하는 부분을 프레임워크에서 처리해주고


개발자는 비지니스 모델에만 집중할 수 있는 구조를 갖춰주고 있다.


빠른 생산성 개발자가 미친짓만 안한다면 높은 안정성을 보장 할 수 있기에


이제는 거의 대 다수가 프레임워크를 사용해서 개발하고 있다.


시대가 지날 수록 성능보다는 생산성이 중요해지기 마련이다.


큰 그림을 그리는 연습을 하자


Posted by 행복한 프로그래머 궁금쟁이박

댓글을 달아 주세요