'android frameworks'에 해당되는 글 2건

(3) InputListener.cpp
frameworks/base/services/input/InputListener.cpp

 

(http://androidxref.com/source/history/frameworks/base/services/input/InputListener.cpp)

 

Introduced the concept of an InputListener to further decouple the InputReader from the InputDispatcher.

The InputListener exposes just the minimum interface that the InputReader needs to communicate with the

outside world. The InputReader passes arguments to the InputListener by reference, which makes it easy to

queue them up.

 


(4) InputDispatcher.cpp
frameworks/base/services/input/InputDispatcher.cpp

 

InputListener를 자세히 보진 않았지만 사실은 InputReader에서 InputListener를 거쳐서 InputDispatcher로 들어옴

 

notifyKey(){
     KeyEvent 생성 
     enqueueInboundEventLocked(KeyEntry)

}
notifyMotion(){
     MotionEvent 생성 
     enqueueInboundEventLocked(MotionEntry)

}

 

enqueueInboundEventLocked()함수에서는 KeyEntry/MotionEntry를 queue에 저장하고 Event 내용에 따라 정보를 갱신한다.

mInboundQueue.enqueueAtTail(entry);

여기까지는 InputReader에 의해 호출된 함수가 Queue에 Event 내용을 저장하는 과정이다. (참고: http://marujj.tistory.com/?page=8)


지금부터는 InputDispatcher의 Thread, 실질적인 동작에 대해 분석.

InputDispatcher Class는 기본적으로 아래의 InputDispatcherThread에 의해서 동작한다.

 

dispatchOnce()

dispatchOnceInnerLocked()
     case EventEntry::TYPE_KEY: 
          --> dispatchKeyLocked 
          --> dispatchEventToCurrentInputTargetsLocked
     case EventEntry::TYPE_MOTION: 
          --> dispatchMotionLocked
          --> dispatchEventToCurrentInputTargetsLocked

 

dispatchEventToCurrentInputTargetsLocked
    --> prepareDispatchCycleLocked
    --> enqueueDispatchEntryLocked

...

// Enqueue the dispatch entry./
connection->outboundQueue.enqueueAtTail(dispatchEntry);

 

여기서 Connection은 이것!

InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
     const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
     status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
     monitor(monitor), inputPublisher(inputChannel), 
     lastEventTime(LONG_LONG_MAX), lastDispatchTime(LONG_LONG_MAX) {
}

 

이 Connection과 위쪽에서 연결되는 부분은 WindowManagerService이다

 

1) frameworks/base/service/java/com/android/server/wm/WindowManagerService.java

addWindow()에서 mInputManager.registerInputChannel(win.mInputChannel, win.mInputWindowHandle);

2) frameworks/base/core/java/android/view/InputQueue.java

registerInputChannel() --> nativeRegisterInputChannel()

3) frameworks/base/core/jni/android_view_InputQueue.cpp

android_view_InputQueue_nativeRegisterInputChannel()
--> registerInputChannel()    // 여기서 Connection 생성

 

이제 강적 바인더구나.. 바인더 공부를 해야겠다ㅠㅠ

 

'Android' 카테고리의 다른 글

Android Event Dispatch Process  (0) 2012.06.21
Android GestureDetector  (0) 2012.06.12
Monkey Test 옵션 정리  (0) 2012.02.20
인사이드 안드로이드 Chapter5  (0) 2012.02.02
인사이드 안드로이드 Chapter4  (0) 2012.02.02
블로그 이미지

민둥

,

(1) EventHub.cpp

frameworks/base/services/input/EventHub.cpp (ICS)

 

(참고: http://dry-kiss.blogspot.kr/2012/03/android-adb.html)
모든 event는 /dev/input/ 으로 들어온다.

 

입력 디바이스 이벤트 처리
(참고: http://blog.daum.net/baramjin/16011045)

 

EventHub에서는 디바이스 open, close, read 등등의 작업을 담당한다.

실제로 해당 method들의 호출은 InputReader에서 하게 된다.

 

디바이스에서 Event를 읽어오는 method.

getEvents()


디바이스에서 이벤트를 읽어올때는 struct input_event 타입으로 읽어오게 된다.

 

struct input_event readBuffer[bufferSize]; // input_event 타입의 readBuffer
int32_t readSize = read(device->fd, readBuffer, 
     sizeof(struct input_event) * capacity); // readBuffer에서 값을 읽어오고
const struct input_event& iev = readBuffer[i]; // 그 중에 하나를 꺼내어 RawEvent 타입으로 가져온다
...


RawEvent event;
event->when = now;
event->deviceId = deviceId;
event->type = iev.type;
event->scanCode = iev.code;
event->value = iev.value;
...

 

 

(2) InputReader.cpp

frameworks/base/services/input/InputReader.cpp

 

size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

 

여기서 mEventBuffer가 EventHub에서 받아온 RawEvent이다.

mEventBuffer의 선언은 InputReader.h에서 다음과 같이되어있고.. RawEvent mEventBuffer[EVENT_BUFFER_SIZE];

 

if (count) {
     processEventsLocked(mEventBuffer, count);
}

 

EventBuffer에 이벤트를 받아오면, 받아온 이벤트 개수만큼 process진행한다.

Device add/remove event가 아닌 다른 이벤트들은 deviceId와 함께

processEventsForDeviceLocked(deviceId, rawEvent, batchSize); 로 전달!

 

device->process(rawEvents, count);

 

각 InputDevice의 process()로 event를 보낸다.

InputDevice::process의 주석을 참고삼아 읽어보자.

 

void InputDevice::process(const RawEvent* rawEvents, size_t count) {
// Process all of the events in order for each mapper.
// We cannot simply ask each mapper to process them in bulk because mappers may
// have side-effects that must be interleaved.  For example, joystick movement events
// gamepad button presses are handled by different mappers but they should be dispatched
// in the order received.

 

...

for (size_t i = 0; i < numMappers; i++) {
 InputMapper* mapper = mMappers[i];
 mapper->process(rawEvent);
}


그런데 아래 for문을 보면 모든 등록된 mapper로 event를 보내? 모든?

 

모든 InputDevice들은 device create할때 mMapper에 등록되도록 하는데 (InputDevice* InputReader::createDeviceLocked)
이때, Switch-like, Keyboard-like, Cursor-like, Touchscreen/touchpad, Joystick-like device들만 mapper에 등록되고 External device들은 빠진다. External device에서 나오는 센서 이벤트들은 따로 처리되는듯 하다. 이건 다음에...


모든 mapper로 event를 보내긴 하지만, 각 mapper들에서는 type을 보고 이벤트를 처리할지 결정한다.

현재 ICS에서 지원하는것으로 보이는 Mapper의 종류들은 다음과 같다.

 

CursorInputMapper {
    mCursorButtonAccumulator
    mCursorButtonAccumulator
    mCursorScrollAccumulator
}
TouchInputMapper {
    mCursorButtonAccumulator
    mCursorScrollAccumulator
    mTouchButtonAccumulator
}
SingleTouchInputMapper {
    TouchInputMapper
    mSingleTouchMotionAccumulator
}
MultiTouchInputMapper {
    TouchInputMapper
    mMultiTouchMotionAccumulator
}
SwitchInputMapper {
    switch (rawEvent->type) case EV_SW
}
KeyboardInputMapper {
    switch (rawEvent->type) case EV_KEY
}
JoystickInputMapper {
    switch (rawEvent->type) case EV_ABS, case EV_SYN
}

 

Mapper들의 내부에서는 다른 Mapper를 부르거나 Accumulator를 불러 동작!

 

CursorButtonAccumulator::process --> (rawEvent->type == EV_KEY) 
     BTN_LEFT, BTN_RIGHT, BTN_MIDDLE, ...
CursorMotionAccumulator::process --> (rawEvent->type == EV_REL)
     REL_X, REL_Y
CursorScrollAccumulator::process --> (rawEvent->type == EV_REL)
     REL_WHEEL, REL_HWHEEL
TouchButtonAccumulator::process --> (rawEvent->type == EV_KEY) 
     BTN_TOUCH, BTN_STYLUS, BTN_TOOL_FINGER, ...s
SingleTouchMotionAccumulator::process --> (rawEvent->type == EV_ABS)
     ABS_X, ABS_Y, ABS_PRESSURE, ...
MultiTouchMotionAccumulator::process --> (rawEvent->type == EV_ABS)
     ABS_MT_POSITION_X, ABS_MT_POSITION_Y, ABS_MT_TOUCH_MAJOR, ...

 

모든 Event들은 그 타입에 따라서 notifyMotion 또는 notifyKey를 통해서 InputDispatcher로 전달된다.
EV_SYN --> 각 mapper의 sync() --> notifyMotion/notifyKey 의 형태.

 

InputDispatcher는 뒤에 계속..

 

'Android' 카테고리의 다른 글

Android Event Dispatch Process (2)  (0) 2012.06.21
Android GestureDetector  (0) 2012.06.12
Monkey Test 옵션 정리  (0) 2012.02.20
인사이드 안드로이드 Chapter5  (0) 2012.02.02
인사이드 안드로이드 Chapter4  (0) 2012.02.02
블로그 이미지

민둥

,