(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
블로그 이미지

민둥

,

Android GestureDetector

Android 2012. 6. 12. 15:40

frameworks/base/core/java/android/view/GestureDetector.java


public class GestureDetector {
public interface OnGestureListener
public interface OnDoubleTapListener
public static class SimpleOnGestureListener implements OnGestureListenerOnDoubleTapListener
...

}


public interface OnGestureListener {
/* 터치하려고 손을 대면 발생하는 이벤트 */
boolean onDown(MotionEvent e);  
/* 짧은 시간 동안 누르면 발생하는 이벤트 */
void onShowPress(MotionEvent e);
/* 한 번 터치 했을 때 발생하는 이벤트 */
boolean onSingleTapUp(MotionEvent e);
/* 스크롤 시에 발생하는 이벤트 */
boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
/* 길게 눌렀을 때 발생하는 이벤트 */
void onLongPress(MotionEvent e);
/* 스크롤에서 끝을 살짝 튕기는 동작에서 발생하는 이벤트 */
boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);

}


public interface OnDoubleTapListener {
/* 한 번 터치하고 다음 이벤트가 들어오지 않을 때한 번 터치가 확실하다고 확인 해주는 이벤트*/
boolean onSingleTapConfirmed(MotionEvent e);
/* 두 번 터치 */
boolean onDoubleTap(MotionEvent e);
/* 두 번 터치, 두 번째 터치에 Down, Move, Up 이벤트를 포함 */
boolean onDoubleTapEvent(MotionEvent e);

}


그렇다면 Multi-touch에 관련한 Gesture는 어떻게 하는거지?

à 2.2(Froyo)부터 ScaleGestureDetector 제공


012




참고: 

http://blog.vizpei.kr/94697746

http://blog.vizpei.kr/94770746






'Android' 카테고리의 다른 글

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

민둥

,

Repo recursive copy

Else 2012. 6. 4. 16:44

git root 폴더에 해당하는 dir를 recursive하게 돌면서 cp


repo forall -c 'cp -v  .gitignore ~/project/g1_tdr/${REPO_PATH}'


Shell Script 

#!/bin/sh


DEST=~/project/g1_tdr/android


for file in `find . -name .gitignore`; do

        dir=$DEST"/"`dirname $file`"/.gitignore";

        #echo $file" -> "$dir;

        cp -v $file $dir

done


'Else' 카테고리의 다른 글

JAVA: Read binary file written in C  (0) 2012.03.12
find 사용법  (0) 2012.02.22
블로그 이미지

민둥

,
C에서 쓴 binary file을 Java에서 읽기위해서 온갖 삽질을 하다가..

- encoding문제인가 싶어서 온갖 encoding관련 검색을 하고 변경해봤지만 이건 아니고.
- Java에서 unsigned를 다루지 못해서 생긴 문제인가 싶어서 찾아봤지만 이것도 아니고.
- Big/little endian문제였다는것을 발견... 

Java에서는 Big endian으로만 데이터를 취급한다.
따라서 1) C에서 파일을 작성할때 Big endian으로 써주거나.
아니면 반대로 2) Java에서 읽을때 byte 를 거꾸로 읽어줘야 제대로 된 값을 가져올 수 있다.

나는 C에서 써주는 방법이 좀 더 간단하므로 이 방법을 택했음

1) C에서 작성하는 방법

 #include <arpa/inet.h>
 x = htonl(x);


2) Java에서 읽는 방법
( http://www.blah-blah.ch/it/programming/java-unsigned-int/ )

public static long readBytesLittle2Big(DataInputStream d, int iHowmany) throws IOException {
byte[] b = new byte[iHowmany];
ByteBuffer bb = ByteBuffer.allocate(iHowmany);
for (int x=0;x<iHowmany;x++)
{
b[x] = d.readByte();
}
/*Here I read stuff from disc which is saved in little endian order which I have to convert into big endian*/
for (int x=0;x<iHowmany;x++)
{
bb.put(iHowmany-1-x, b[x]);
}
bb.rewind();
return bb.getInt();
}



'Else' 카테고리의 다른 글

Repo recursive copy  (0) 2012.06.04
find 사용법  (0) 2012.02.22
블로그 이미지

민둥

,