美文网首页
Android之input 系统服务分析

Android之input 系统服务分析

作者: 锄禾豆 | 来源:发表于2022-01-23 00:00 被阅读0次

问题
1.PhoneWindowManager.interceptKeyBeforeQueueing/interceptKeyBeforeDispatching怎么跟系统服务input关联?
2.Activity.dispatchTouchEvent/dispatchKeyEvent怎么跟系统服务input的触摸/按键事件关联?
3.PowerManagerService.userActivityFromNative怎么被系统服务input触发?

adb查询

adb shell cmd input

adb shell dumpsys input

代码

frameworks/base/services/java/com/android/server
SystemServer.java

frameworks/base/services/core/java/com/android/server/wm
WindowManagerService.java

frameworks/base/services/core/java/com/android/server/policy
PhoneWindowManager.java

frameworks/base/services/core/java/com/android/server/input
InputManagerService.java

frameworks/base/services/core/jni/
com_android_server_input_InputManagerService.cpp(NativeInputManager)

frameworks/native/services/inputflinger
InputManager.cpp
InputDispatcher.cpp(InputDispatcherThread)
InputReader.cpp(InputReaderThread)

注:
7.1

分析

1.input启动

com.android.server.SystemServer

private void startOtherServices() {
            ···
            traceBeginAndSlog("StartInputManagerService");
            inputManager = new InputManagerService(context);
            traceEnd();
            ···
            wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
            traceEnd();
            ···
            traceBeginAndSlog("StartInputManager");
            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
            inputManager.start();
            traceEnd();
            ···
            final InputManagerService inputManagerF = inputManager;
            mActivityManagerService.systemReady(new Runnable() {
                public void run() {
                    ···
                    try {
                        // TODO(BT) Pass parameter to input manager
                        if (inputManagerF != null) inputManagerF.systemRunning();
                    } catch (Throwable e) {
                        reportWtf("Notifying InputManagerService running", e);
                    }
                    ···
                }
            }
            ···
}

1)WindowManagerService和InputManagerService是强耦合。WindowManagerService的main方法注入inputmanager
2)input服务设置window服务的回调方法。也就是当input有变动,可通过回调方法通知window。

2.input的初始化

com.android.server.input.InputManagerService

/* InputManagerService的构造方法*/
public InputManagerService(Context context) {
        ······
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
        ······
}

 public void start() {
        nativeStart(mPtr);
        ······
}

以上两个方法都关联native层

3.input的nativie层
1)关键对象的初始化及调用

com_android_server_input_InputManagerService.cpp

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    ···
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());//注意,serviceObj就是InputManagerService
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

a)将InputManagerService对象传到native层,并传给创建的NativeInputManager对象
b)启动NativeInputManager的InputManager

2)NativeInputManager初始化

com_android_server_input_InputManagerService.cpp

class NativeInputManager : public virtual RefBase,
    public virtual InputReaderPolicyInterface,
    public virtual InputDispatcherPolicyInterface,
    public virtual PointerControllerPolicyInterface

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    ·······
    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);
    ······
    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}

a)NativeInputManager继承InputReaderPolicyInterface,关联InputReader事件,例如:notifyInputDevicesChanged
NativeInputManager继承InputDispatcherPolicyInterface,关联InputDispatcher事件,例如:interceptKeyBeforeQueueing/interceptKeyBeforeDispatching
b)InputManagerService对象在Native存在的名称是mServiceObj
c)初始化InputManager,并将InputManager和EventHub关联

3)InputManager初始化及启动

InputManager.cpp
InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    ···
    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    ···
    return OK;
}

a)InputManager中创建了InputReader和InputDispatcher。InputReader负责从底层(通过EventHub)读取数据,InputDispatcher负责分发来自InputReader数据
b)InputReader关联上EventHub、InputDispatcher的回调类(InputListenerInterface)、InputReader本身的回调类(InputReaderPolicyInterface)
c)InputManager创建两个线程mReaderThread、mDispatcherThread,

4-1)线程简介,以InputReaderThread为例

InputReader.h
class InputReaderThread : public Thread {
public:
    InputReaderThread(const sp<InputReaderInterface>& reader);
    virtual ~InputReaderThread();

private:
    sp<InputReaderInterface> mReader;

    virtual bool threadLoop();
};

InputReader.cpp
InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
        Thread(/*canCallJava*/ true), mReader(reader) {
}

InputReaderThread::~InputReaderThread() {
}

bool InputReaderThread::threadLoop() {
    mReader->loopOnce();
    return true;
}

当线程run起来,则调用threadLoop,因为threadLoop返回true,则会一直循环threadLoop

4-2)分析InputReader

InputReader.cpp
a)InputReader构造函数
InputReader::InputReader(const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& policy,
        const sp<InputListenerInterface>& listener) :
        mContext(this), mEventHub(eventHub), mPolicy(policy),
        mGlobalMetaState(0), mGeneration(1),
        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    mQueuedListener = new QueuedInputListener(listener);
    ···
}
简单的说,policy为NativeInputManager对象,listener为InputDispatcher对象
,此时mQueuedListener关联了InputDispatcher对象

b)执行loopOnce
void InputReader::loopOnce() {
    ···
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
    { // acquire lock
        ···
        if (count) {
            //增加InputDevice设备或者处理业务
            processEventsLocked(mEventBuffer, count);
        }
        ···
    } // release lock
    ···
    if (inputDevicesChanged) {
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }
    ···
    mQueuedListener->flush();
}

c)关注processEventsLocked
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        ···
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            ···
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                break;
            ···
        }
        ···
    }
}
(1)addDeviceLocked会初始化InputDevice,并且addMapper很多对象进行,例如KeyboardInputMapper、MultiTouchInputMapper、SingleTouchInputMapper
(2)processEventsForDeviceLocked是处理业务

d)关注processEventsForDeviceLocked
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
    ···
    InputDevice* device = mDevices.valueAt(deviceIndex);
    ···
    device->process(rawEvents, count);
}

4-2-1)如果是按键事件,则调用KeyboardInputMapper
11)关注KeyboardInputMapper.process

void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
    case EV_KEY: {
        int32_t scanCode = rawEvent->code;
        int32_t usageCode = mCurrentHidUsage;
        ···
        if (isKeyboardOrGamepadKey(scanCode)) {
            processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
        }
        break;
    }
    ···
    }
}

12)关注KeyboardInputMapper.processKey

void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t scanCode,
        int32_t usageCode) {
    ···
    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
    getListener()->notifyKey(&args);
}

(1)getListener()是InputDispather
(2)调用Dispatcher.notifyKey

4-2-2)如果是触摸事件,则调用MultiTouchInputMapper
11)MultiTouchInputMapper.process

void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
    TouchInputMapper::process(rawEvent);

    mMultiTouchMotionAccumulator.process(rawEvent);
}

(1)切换成执行TouchInputMapper.process
(2)过程很复杂,只挑过程

12)省略复杂分析过程

TouchInputMapper.process ---> TouchInputMapper.sync ---> TouchInputMapper.processRawTouches --->TouchInputMapper.cookAndDispatch ---> TouchInputMapper.dispatchTouches ---> TouchInputMapper.dispatchMotion

void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
        int32_t action, int32_t actionButton, int32_t flags,
        int32_t metaState, int32_t buttonState, int32_t edgeFlags,
        const PointerProperties* properties, const PointerCoords* coords,
        const uint32_t* idToIndex, BitSet32 idBits, int32_t changedId,
        float xPrecision, float yPrecision, nsecs_t downTime) {
    ···
    NotifyMotionArgs args(when, getDeviceId(), source, policyFlags,
            action, actionButton, flags, metaState, buttonState, edgeFlags,
            mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
            xPrecision, yPrecision, downTime);
    getListener()->notifyMotion(&args);
}

(1)getListener()是InputDispather
(2)调用Dispatcher.notifyMotion

5)分析InputDispatcher
a)InputDispatcherThread调用

bool InputDispatcherThread::threadLoop() {
    mDispatcher->dispatchOnce();
    return true;
}

循环执行threadLoop

b)InputDispatcher构造函数

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy),
    mPendingEvent(NULL), mLastDropReason(DROP_REASON_NOT_DROPPED),
    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
    mNextUnblockedEvent(NULL),
    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
    ···
}

mPolicy其实就是NativeInputManager

c)InputDispatcher.dispatchOnce

void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        ···
        if (!haveCommandsLocked()) {//队列mCommandQueue,如果没有命令则走进去
            dispatchOnceInnerLocked(&nextWakeupTime);
        }

        if (runCommandsLockedInterruptible()) {//执行命令
            nextWakeupTime = LONG_LONG_MIN;
        }
    } // release lock

    ···
    mLooper->pollOnce(timeoutMillis);//wait。等待mLooper.wake
}

(1)关注dispatchOnceInnerLocked的执行
(2)当线程wait时,只有超时或者wake才能触发线程重新执行threadLoop,即重新执行dispatchOnce

d)InputDispatcher.dispatchOnceInnerLocked

void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
    ···
    if (! mPendingEvent) {
        if (mInboundQueue.isEmpty()) {//如果队列为null,则最后直接return
            ···
            if (!mPendingEvent) {
                return;
            }
        } else {
            //从队列mInboundQueue取出对象
            mPendingEvent = mInboundQueue.dequeueAtHead();
            traceInboundQueueLengthLocked();
        }

        //pokeUserActivityLocked最后回到PowerManagerService.userActivityFromNative
        if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            pokeUserActivityLocked(mPendingEvent);
        }

        // Get ready to dispatch the event.
        resetANRTimeoutsLocked();
    }
    ···
    switch (mPendingEvent->type) {
    ···
    case EventEntry::TYPE_KEY: {
        KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
        ···
        //分发按键事件
        done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
        break;
    }

    case EventEntry::TYPE_MOTION: {
        MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
        ···
        //分发触摸事件
        done = dispatchMotionLocked(currentTime, typedEntry,
                &dropReason, nextWakeupTime);
        break;
    }

    default:
        ALOG_ASSERT(false);
        break;
    }

    if (done) {
        ···
        releasePendingEventLocked();
        *nextWakeupTime = LONG_LONG_MIN;  // force next poll to wake up immediately
    }
}

(1)关注队列mInboundQueue。这里的数据来源由InputReader传递而来
(2)根据TYPE类型,执行触摸或按键事件

e-1)以按键事件为例,分析来自InputReader的数据
11)InputDispatcher.notifyKey

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    ···
    //mPolicy即NativeInputManager,回调到InputManagerService.interceptKeyBeforeQueueing
    //即由PhoneWindowManager.interceptKeyBeforeQueueing实现
    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);

    bool needWake;
    { // acquire lock
        mLock.lock();

        if (shouldSendKeyToInputFilterLocked(args)) {//过滤器
            mLock.unlock();

            policyFlags |= POLICY_FLAG_FILTERED;
            if (!mPolicy->filterInputEvent(&event, policyFlags)) {
                return; // event was consumed by the filter
            }

            mLock.lock();
        }

        int32_t repeatCount = 0;
        //创建KeyEntry对象
        KeyEntry* newEntry = new KeyEntry(args->eventTime,
                args->deviceId, args->source, policyFlags,
                args->action, flags, keyCode, args->scanCode,
                metaState, repeatCount, args->downTime);

        //将newEntry插入队列
        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock

    if (needWake) {//是否唤醒InputDispatcherThread线程
        mLooper->wake();
    }
}

12)InputDispatcher.enqueueInboundEventLocked

bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.isEmpty();
    //将entry放入mInboundQueue队列
    mInboundQueue.enqueueAtTail(entry);
    ···

    switch (entry->type) {
    case EventEntry::TYPE_KEY: {
        ···
        break;
    }

    case EventEntry::TYPE_MOTION: {
        ···
        break;
    }
    }

    return needWake;
}

13)调用mLooper->wake(),则回到InputDispatcher.dispatchOnce
14)执行InputDispatcher.dispatchKeyLocked

bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
        DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ···
    // Give the policy a chance to intercept the key.
    if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN) {
        if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
            //拦截事件分析
            CommandEntry* commandEntry = postCommandLocked(
                    & InputDispatcher::doInterceptKeyBeforeDispatchingLockedInterruptible);
            if (mFocusedWindowHandle != NULL) {
                commandEntry->inputWindowHandle = mFocusedWindowHandle;
            }
            commandEntry->keyEntry = entry;
            entry->refCount += 1;
            return false; // wait for the command to run
        } else {
            entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
        }
    } else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
        if (*dropReason == DROP_REASON_NOT_DROPPED) {
            *dropReason = DROP_REASON_POLICY;
        }
    }
    ···
    //按键分发
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

(1)如果满足拦截条件,则将对象插入mCommandQueue队列中,从而回到dispatchOnce调用函数runCommandsLockedInterruptible,从而达到PhoneWindowManager.interceptKeyBeforeDispatching的业务实现
(2)如果PhoneWindowManager拦截成功了,则按键不再继续分发;如果没有拦截,则通过dispatchOnce的循环执行,再进行dispatchEventLocked分发,此时entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_SKIP
15)InputDispatcher.dispatchEventLocked进行数据分发

void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
        EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
    ···
    //pokeUserActivityLocked最后回到PowerManagerService.userActivityFromNative
    pokeUserActivityLocked(eventEntry);

    for (size_t i = 0; i < inputTargets.size(); i++) {
        const InputTarget& inputTarget = inputTargets.itemAt(i);

        //socket通信
        ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
        if (connectionIndex >= 0) {
            sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
            prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
        } else {
            ···
        }
    }
}

e-2)以触摸事件为例,分析来自InputReader的数据
此过程与按键流程相差无几,我们重点分析差一点
12)InputDispatcher.notifyMotion

void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
    ···
    //mPolicy即NativeInputManager,回调到InputManagerService.interceptMotionBeforeQueueingNonInteractive
    //即由PhoneWindowManager.interceptMotionBeforeQueueingNonInteractive实现
    mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);

    bool needWake;
    { // acquire lock
        mLock.lock();

        ···

        // Just enqueue a new motion event.
        MotionEntry* newEntry = new MotionEntry(args->eventTime,
                args->deviceId, args->source, policyFlags,
                args->action, args->actionButton, args->flags,
                args->metaState, args->buttonState,
                args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
                args->displayId,
                args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);

        //加入队列
        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock

    if (needWake) {//唤醒线程
        mLooper->wake();
    }
}

(1)触摸事件在PhoneWindowManager中也有对应的方法:interceptMotionBeforeQueueingNonInteractive

12)InputDispatcher.dispatchMotionLocked

bool InputDispatcher::dispatchMotionLocked(
        nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
    ···
    if (isPointerEvent) {//找窗口
        // Pointer event.  (eg. touchscreen)
        injectionResult = findTouchedWindowTargetsLocked(currentTime,
                entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
    } else {
        // Non touch event.  (eg. trackball)
        injectionResult = findFocusedWindowTargetsLocked(currentTime,
                entry, inputTargets, nextWakeupTime);
    }
    ···
    //分发触摸事件
    dispatchEventLocked(currentTime, entry, inputTargets);
    return true;
}

(1)findTouchedWindowTargetsLocked找关键窗口。此过程很复杂,不做解析
(2)dispatchEventLocked分发触摸事件

总结

1.针对按键事件,反馈到PhoneWindowManager的方法执行顺序如下
(1)interceptKeyBeforeQueueing --> (2)interceptKeyBeforeDispatching --> (3)app:Activity.dispatchKeyEvent
如果(1)拦截了,就不会再执行(2)、(3),如果(2)拦截了,就不会再执行(3),整个过程时串行存在

2.针对触摸事件,反馈到PhoneWindowManager的方法执行顺序如下
(1)interceptMotionBeforeQueueingNonInteractive --> (2)app:Activity.dispatchTouchEvent
这里一般在屏幕黑的情况下做处理

3.不管任何一种事件,都会触发PowerManagerService.userActivityFromNative
主要由Dispatcher.pokeUserActivityLocked执行

参考学习

https://www.jianshu.com/p/debbc56ab2d3
https://www.jianshu.com/p/d4988d632e82
https://blog.csdn.net/aeolia_zhang/article/details/19914467
https://blog.csdn.net/lwz622/article/details/80769351
https://blog.csdn.net/learnrose/article/details/6236890
https://segmentfault.com/a/1190000019032508?utm_source=tag-newest
https://www.jianshu.com/p/f05d6b05ba17
https://blog.csdn.net/lilian0118/article/details/28617185
https://blog.csdn.net/woshihongliu/article/details/82867619

相关文章

网友评论

      本文标题:Android之input 系统服务分析

      本文链接:https://www.haomeiwen.com/subject/vexshrtx.html