Android Input系统2 输入系统启动

一 概述

上一篇文章介绍了输入系统的大体运作流程,这篇文章详细介绍 Input 系统的启动。

Input 模块的主要组成:

  • Native 层的 InputReader 负责从 EventHub 取出事件并处理,再交给 InputDispatcher
  • Native 层的 InputDispatcher 接收来自 InputReader 传递过来的输入事件,并记录 WMS 的窗口信息,用于派发事件到合适的窗口
  • Java 层的 InputManagerService 跟 WMS 交互,WMS 记录所有窗口信息,并同步更新到 IMS,为 InputDispatcher 正确派发事件到 ViewRootImpl 提供保障

Input 相关的动态库:

libinputflinger.so:frameworks/native/services/inputflinger/
libinputservice.so:frameworks/base/libs/input/
libinput.so: frameworks/native/libs/input/

涉及代码如下:

frameworks/native/services/inputflinger/
  - InputDispatcher.cpp
  - InputReader.cpp
  - InputManager.cpp
  - EventHub.cpp
  - InputListener.cpp

frameworks/native/libs/input/
  - InputTransport.cpp
  - Input.cpp
  - InputDevice.cpp
  - Keyboard.cpp
  - KeyCharacterMap.cpp
  - IInputFlinger.cpp

frameworks/base/services/core/
  - java/com/android/server/input/InputManagerService.java
  - jni/com_android_server_input_InputManagerService.cpp

1.1 整体框架类图

InputManagerService 作为 system_server 中的重要服务,继承于 IInputManager.Stub, 作为 Binder 服务端,那么 Client 位于 InputManager 的内部通过 IInputManager.Stub.asInterface() 获取 Binder 代理端,C/S 两端通信的协议是由 IInputManager.aidl 来定义的。
在这里插入图片描述
Input 模块所涉及的重要类的关系如下:
在这里插入图片描述

  • InputManagerService 位于 Java 层的 InputManagerService.java 文件,其成员 mPtr 指向 Native 层的 NativeInputManager 对象
  • NativeInputManager 位于 Native 层的 com_android_server_input_InputManagerService.cpp 文件,其成员 mServiceObj 指向 Java 层的 IMS 对象;其成员 mLooper 是指 “android.display” 线程的 Looper
  • InputManager 位于 libinputflinger 中的 InputManager.cpp 文件
    InputDispatcher 和 InputReader 的成员变量 mPolicy 都是指 NativeInputManager 对象
    InputReader 的成员 mQueuedListener,数据类型为 QueuedInputListener;通过其内部成员变量 mInnerListener 指向 InputDispatcher 对象;这便是 InputReader 跟 InputDispatcher 交互的中间枢纽。

1.2 启动调用栈

IMS 服务是伴随着 system_server 进程的启动而启动的,整个调用过程如下:

InputManagerService(初始化)
    nativeInit
        NativeInputManager            
            InputManager
                InputDispatcher
                    Looper
                InputReader
                    EventHub
                    QueuedInputListener
                InputReaderThread
                InputDispatcherThread
IMS.start(启动)
    nativeStart
        InputManager.start
            InputReaderThread->run
            InputDispatcherThread->run

整个过程首先创建如下对象:NativeInputManager,EventHub,InputManager, InputDispatcher,InputReader,InputReaderThread,InputDispatcherThread。 接着便是启动两个工作线程 InputReaderThread 和 InputDispatcherThread。

二 启动过程

private void startOtherServices() {
        ......
        InputManagerService inputManager = null;
        //初始化IMS对象
        inputManager = new InputManagerService(context);
        //把inputManager的引用放到WMS中,建立联系
        wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore, new PhoneWindowManager());
        ServiceManager.addService(Context.WINDOW_SERVICE, wm);
        ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
        //设置回调,将WMS中的InputManagerCallback设置到inputManager中
        //这里说明了最终如何回调到PhoneWindowManager
        inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
        inputManager.start();
        ......
}

2.1 InputManagerService

public InputManagerService(Context context) {
   this.mContext = context;
   // 创建了InputManagerHandler,其Looper是DisplayThead的Looper
   // 运行在线程"android.display"
   this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
   ......
   //初始化native对象
   mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
   LocalServices.addService(InputManagerInternal.class, new LocalService());
}

2.2 nativeInit

static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    //获取native消息队列
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(
            env, messageQueueObj);
    ......
    //创建Native的InputManager
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    //返回Native对象的指针给IMS,IMS后续会用到。IMS保存在mPtr
    return reinterpret_cast<jlong>(im);
}

2.3 NativeInputManager

NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();
    mServiceObj = env->NewGlobalRef(serviceObj);//上层IMS对象
    ......
    // 创建InputManager对象
    mInputManager = new InputManager(this, this);
    defaultServiceManager()->addService(String16("inputflinger"),
            mInputManager, false);
}

此处的 mLooper 是指 “android.display” 线程的 Looper。

2.4 InputManager

sp<InputReaderInterface> mReader;

InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    //创建InputDispatcher对象
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mClassifier = new InputClassifier(mDispatcher);
    //创建InputReader对象
    mReader = createInputReader(readerPolicy, mClassifier);
    initialize();
}

InputDispatcher 和 InputReader 的 mPolicy 成员变量都是指 NativeInputManager 对象:

class NativeInputManager : public virtual RefBase,
    public virtual InputReaderPolicyInterface,
    public virtual InputDispatcherPolicyInterface,
    public virtual PointerControllerPolicyInterface {
    ......
}

2.5 createInputReader

framework/native/services/inputflinger/InputReaderFactory.cpp

sp<InputReaderInterface> createInputReader(
        const sp<InputReaderPolicyInterface>& policy,
        const sp<InputListenerInterface>& listener) {
    return new InputReader(new EventHub(), policy, listener);
}

InputReader::InputReader(const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& policy,
        const sp<InputListenerInterface>& listener) :
        mContext(this), mEventHub(eventHub), mPolicy(policy),
        mNextSequenceNum(1), mGlobalMetaState(0), mGeneration(1),
        mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
        mConfigurationChangesToRefresh(0) {
    // 创建输入监听对象
    mQueuedListener = new QueuedInputListener(listener);
    {
        AutoMutex _l(mLock);
        refreshConfigurationLocked(0);
        updateGlobalMetaStateLocked();
    }
}

此处的 listener 便是 InputDispatcher 对象,赋值给了 mQueuedListener 的成员变量 mInnerListener,这样 InputDispatcher 和 InputReader 便建立起了联系。同时我们可以看到在生成 InputReader 的时候,new 了一个 EventHub 对象。

2.6 EventHub

EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(nullptr), mClosingDevices(nullptr),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
    acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
    //创建epoll对象,mEpollFd为epoll对象的描述符
    mEpollFd = epoll_create1(EPOLL_CLOEXEC);
    //创建inotify对象,mINotifyFd为inotify对象的描述符
    mINotifyFd = inotify_init();
    //此处DEVICE_PATH为"/dev/input",监听该目录下的设备节点创建与删除操作。通过read函数读取事件
    mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
    ......
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;//监听可读事件
    eventItem.data.fd = mINotifyFd;
    //添加INotify到epoll实例
    //EPOLL_CTL_ADD表示增加事件  
    //epoll_ctl将事件监听添加到epoll对象中去。
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);

    int wakeFds[2];
    result = pipe(wakeFds); //创建管道

    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];

    //将pipe的读和写都设置为非阻塞方式
    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);

    eventItem.data.fd = mWakeReadPipeFd;
    //添加管道的读端到epoll实例
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
    ......
}

该方法主要功能:

  • 初始化一些成员变量
  • 创建 epoll 对象
  • 创建 INotify 对象,监听 ”/dev/input” 下设备节点的增删
  • 将 mINotifyFd 添加到 epoll 中,作为一个监控对象
  • 创建非阻塞模式的管道,将管道读取端的可读事件添加到 epoll 中,使 epoll_wait() 返回,唤醒 InputReader 线程

2.7 InputDispatcher

InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy) :
    mPolicy(policy),
    mPendingEvent(nullptr), mLastDropReason(DROP_REASON_NOT_DROPPED),
    mAppSwitchSawKeyDown(false), mAppSwitchDueTime(LONG_LONG_MAX),
    mNextUnblockedEvent(nullptr),
    mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false),
    mFocusedDisplayId(ADISPLAY_ID_DEFAULT),
    mInputTargetWaitCause(INPUT_TARGET_WAIT_CAUSE_NONE) {
    mLooper = new Looper(false);//创建Looper对象
    mReporter = createInputReporter();

    mKeyRepeatState.lastKeyEntry = nullptr;
    //获取分发超时参数
    policy->getDispatcherConfiguration(&mConfig);
}

该方法主要工作:

  • 创建属于自己线程的 Looper 对象
  • 超时参数来自于 IMS,参数默认值 keyRepeatTimeout = 500,keyRepeatDelay = 50

2.8 initialize

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

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

InputDispatcherThread::InputDispatcherThread(
const sp<InputDispatcherInterface>& dispatcher) :
        Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
}

初始化的主要工作就是创建 InputReaderThread 和 InputDispatcherThread 两个线程,一个用于对输入事件的读取,另一个用于对输入事件的分发。

到此整个 InputManagerService 对象的初始化过程已经分析完毕,接下来分析其 start 方法。

2.9 IMS.start

public void start() {
    // 启动native对象
    nativeStart(mPtr);
    Watchdog.getInstance().addMonitor(this);
    //注册触摸点速度和是否显示功能的观察者
    registerPointerSpeedSettingObserver();
    registerShowTouchesSettingObserver();
    registerAccessibilityLargePointerSettingObserver();
    registerLongPressTimeoutObserver();

    mContext.registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            updatePointerSpeedFromSettings();
            updateShowTouchesFromSettings();
            updateAccessibilityLargePointerFromSettings();
            updateDeepPressStatusFromSettings("user switched");
        }
    }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);

    updatePointerSpeedFromSettings(); //更新触摸点的速度
    updateShowTouchesFromSettings(); //是否在屏幕上显示触摸点
    updateAccessibilityLargePointerFromSettings();
    updateDeepPressStatusFromSettings("just booted");
}

2.10 nativeStart

com_android_server_input_InputManagerService.cpp

static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    //此处ptr记录的便是NativeInputManager
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

2.11 InputManager.start

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

可以看到该方法的主要功能是启动 InputReader 和 InputDispatcher 两个线程。

三 总结

分层视角

  • Java 层 InputManagerService:采用 android.display 线程处理 Message
  • JNI 的 NativeInputManager:采用 android.display 线程处理 Message
  • Native 的 InputManager:创建 InputReaderThread 和 InputDispatcherThread 两个线程,以及创建 EventHub

主要功能

  • IMS 服务中的成员变量 mPtr 记录 Native 层的 NativeInputManager 对象
  • IMS 对象的初始化过程的重点在于 native 的初始化,分别创建了以下对象:
     NativeInputManager
     EventHub, InputManager
     InputReader,InputDispatcher
     InputReaderThread,InputDispatcherThread
  • IMS 启动过程的主要功能是启动以下两个线程:
     InputReader:从 EventHub 取出事件并处理,再交给 InputDispatcher
     InputDispatcher:接收来自 InputReader 的输入事件,并派发事件到合适的窗口

从 IMS 的整个启动过程中可知 system_server 进程中有3个线程跟 Input 输入系统息息相关,分别是 android.display,InputReader 和 InputDispatcher。

  • InputDispatcher 线程:属于 Looper 线程,会创建属于自己的 Looper,循环分发消息
  • InputReader 线程:通过 getEvents() 调用 EventHub 读取输入事件,循环读取消息
  • android.display 线程:属于 Looper 线程,用于处理 Java 层的 IMS.InputManagerHandler 和 JNI 层的 NativeInputManager 中指定的 MessageHandler 消息

Input 事件流程:Linux Kernel -> IMS(InputReader -> InputDispatcher) -> WMS -> ViewRootImpl, 后续再进一步介绍。

四 附录

最后列举下整个 input 处理流程中常见的重要对象或结构体,方便查看。

4.1 InputReader.h

4.1.1 InputDevice

class InputDevice {
public:
    InputDevice(InputReaderContext* context, int32_t id,
    int32_t generation, int32_t controllerNumber,
    const InputDeviceIdentifier& identifier, uint32_t classes);
    ......
private:
    InputReaderContext* mContext;
    int32_t mId;
    int32_t mGeneration;
    int32_t mControllerNumber;
    InputDeviceIdentifier mIdentifier;
    std::string mAlias;
    uint32_t mClasses;

    std::vector<InputMapper*> mMappers;

    uint32_t mSources;
    bool mIsExternal;
    std::optional<uint8_t> mAssociatedDisplayPort;
    bool mHasMic;
    bool mDropUntilNextSync;

    typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask,
            int32_t code);
    int32_t getState(uint32_t sourceMask, int32_t code,
            GetStateFunc getStateFunc);

    PropertyMap mConfiguration;
};

4.2 InputDispatcher.h

4.2.1 DropReason

enum DropReason {
        DROP_REASON_NOT_DROPPED = 0,
        DROP_REASON_POLICY = 1,
        DROP_REASON_APP_SWITCH = 2,
        DROP_REASON_DISABLED = 3,
        DROP_REASON_BLOCKED = 4,
        DROP_REASON_STALE = 5,
};

enum InputTargetWaitCause {
        INPUT_TARGET_WAIT_CAUSE_NONE,
        INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY,
        INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY,
};


sp<Looper> mLooper;

EventEntry* mPendingEvent GUARDED_BY(mLock);
Queue<EventEntry> mInboundQueue GUARDED_BY(mLock);
Queue<EventEntry> mRecentQueue GUARDED_BY(mLock);
Queue<CommandEntry> mCommandQueue GUARDED_BY(mLock);


std::unordered_map<int32_t, std::vector<sp<InputWindowHandle>>>
mWindowHandlesByDisplay GUARDED_BY(mLock);
// Get window handles by display, return an empty vector if not found.
std::vector<sp<InputWindowHandle>> getWindowHandlesLocked(int32_t displayId)
const REQUIRES(mLock);
sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken)
const REQUIRES(mLock);
sp<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken)
const REQUIRES(mLock);
bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle)
const REQUIRES(mLock);

// Focus tracking for keys, trackball, etc.
std::unordered_map<int32_t, sp<InputWindowHandle>>
mFocusedWindowHandlesByDisplay GUARDED_BY(mLock);

InputTargetWaitCause mInputTargetWaitCause GUARDED_BY(mLock);
nsecs_t mInputTargetWaitStartTime GUARDED_BY(mLock);
nsecs_t mInputTargetWaitTimeoutTime GUARDED_BY(mLock);
bool mInputTargetWaitTimeoutExpired GUARDED_BY(mLock);
//目标等待的应用
sp<IBinder> mInputTargetWaitApplicationToken GUARDED_BY(mLock);

4.2.2 Connection

class Connection : public RefBase {
    protected:
        virtual ~Connection();

    public:
        enum Status {
            STATUS_NORMAL,//正常状态
            STATUS_BROKEN,//发生无法恢复的错误
            STATUS_ZOMBIE//input channel被注销掉
        };

        Status status;//状态
        sp<InputChannel> inputChannel; //永不为空
        bool monitor;
        InputPublisher inputPublisher;
        InputState inputState;

        // True if the socket is full and no further events can be 
        // published until the application consumes some of the input.
        //当socket占满的同时,应用消费某些输入事件之前无法发布事件,则值为true.
        bool inputPublisherBlocked;

        // Queue of events that need to be published to the connection.
        //需要被发布到connection的事件队列
        Queue<DispatchEntry> outboundQueue;

        // Queue of events that have been published to the 
        // connection but that have not yet received a "finished" response
        // from the application.
        //已发布到connection,但还没有收到来自应用的“finished”响应的事件队列
        Queue<DispatchEntry> waitQueue;
    };

4.2.3 EventEntry

struct EventEntry : Link<EventEntry> {
        //type的取值
        enum {
            TYPE_CONFIGURATION_CHANGED,
            TYPE_DEVICE_RESET,
            TYPE_KEY,//按键事件
            TYPE_MOTION//触摸事件
        };

        uint32_t sequenceNum;
        mutable int32_t refCount;
        int32_t type;//事件类型
        nsecs_t eventTime;//事件时间
        uint32_t policyFlags;
        InjectionState* injectionState;

        bool dispatchInProgress; //初始值为false, 分发过程则设置成true
    };

4.2.4 INPUT_EVENT_INJECTION

enum {
    // 内部使用, 正在执行注入操作
    INPUT_EVENT_INJECTION_PENDING = -1,
    // 事件注入成功
    INPUT_EVENT_INJECTION_SUCCEEDED = 0,
    // 事件注入失败, 由于injector没有权限将聚焦的input事件注入到应用
    INPUT_EVENT_INJECTION_PERMISSION_DENIED = 1,
    // 事件注入失败, 由于没有可用的input target
    INPUT_EVENT_INJECTION_FAILED = 2,
    // 事件注入失败, 由于超时
    INPUT_EVENT_INJECTION_TIMED_OUT = 3
};

4.2.5 InputTarget

struct InputTarget {
    enum {
        FLAG_FOREGROUND = 1 << 0, //事件分发到前台app
        FLAG_WINDOW_IS_OBSCURED = 1 << 1,
        FLAG_SPLIT = 1 << 2, //MotionEvent被拆分成多窗口
        FLAG_ZERO_COORDS = 1 << 3,
        FLAG_DISPATCH_AS_IS = 1 << 8, //
        FLAG_DISPATCH_AS_OUTSIDE = 1 << 9, //
        FLAG_DISPATCH_AS_HOVER_ENTER = 1 << 10, //
        FLAG_DISPATCH_AS_HOVER_EXIT = 1 << 11, //
        FLAG_DISPATCH_AS_SLIPPERY_EXIT = 1 << 12, //
        FLAG_DISPATCH_AS_SLIPPERY_ENTER = 1 << 13, //
        FLAG_WINDOW_IS_PARTIALLY_OBSCURED = 1 << 14,
        //所有分发模式的掩码
        FLAG_DISPATCH_MASK = FLAG_DISPATCH_AS_IS
                | FLAG_DISPATCH_AS_OUTSIDE
                | FLAG_DISPATCH_AS_HOVER_ENTER
                | FLAG_DISPATCH_AS_HOVER_EXIT
                | FLAG_DISPATCH_AS_SLIPPERY_EXIT
                | FLAG_DISPATCH_AS_SLIPPERY_ENTER,
    };
    sp<InputChannel> inputChannel; //目标的inputChannel
    int32_t flags;
    float xOffset, yOffset; //用于MotionEvent
    float globalScaleFactor; //用于MotionEvent
    BitSet32 pointerIds;
};

4.3 InputTransport.h

4.3.1 InputChannel

class InputChannel : public RefBase {
    // 创建一对input channels
    static status_t openInputChannelPair(const String8& name,
            sp<InputChannel>& outServerChannel,
            sp<InputChannel>& outClientChannel);

    status_t sendMessage(const InputMessage* msg); //发送消息
    status_t receiveMessage(InputMessage* msg); //接收消息
    //获取InputChannel的fd的拷贝
    sp<InputChannel> dup() const;

private:
    void setFd(int fd);
    
    std::string mName;
    int mFd = -1;

    sp<IBinder> mToken = nullptr;
};

sendMessage 的返回值

  • OK:代表成功
  • WOULD_BLOCK:代表 Channel 已满
  • DEAD_OBJECT:代表 Channel 已关闭

receiveMessage 的返回值

  • OK:代表成功
  • WOULD_BLOCK:代表 Channel 为空
  • DEAD_OBJECT:代表 Channel 已关闭

4.3.2 InputPublisher

class InputPublisher {
public:
    //获取输入通道
    inline sp<InputChannel> getChannel() { return mChannel; }
    status_t publishKeyEvent(...); //将key event发送到input channel
    status_t publishMotionEvent(...); //将motion event发送到input channel
    //接收来自InputConsumer发送的完成信号
    status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);
private:
    sp<InputChannel> mChannel;
};

4.3.3 InputConsumer

class InputConsumer {
public:
    inline sp<InputChannel> getChannel() { return mChannel; }
    status_t consume(...); //消费input channel的事件
    //向InputPublisher发送完成信号
    status_t sendFinishedSignal(uint32_t seq, bool handled);
    bool hasDeferredEvent() const;
    bool hasPendingBatch() const;
private:
    sp<InputChannel> mChannel;
    InputMessage mMsg; //当前input消息
    bool mMsgDeferred;
    Vector<Batch> mBatches; //input批量消息
    Vector<TouchState> mTouchStates;
    Vector<SeqChain> mSeqChains;
    status_t consumeBatch(...);
    status_t consumeSamples(...);
    static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg);
    static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg);
}

4.4 input.h

4.4.1 KeyEvent

class KeyEvent : public InputEvent {
    ......
    protected:
        int32_t mAction;
        int32_t mFlags;
        int32_t mKeyCode;
        int32_t mScanCode;
        int32_t mMetaState;
        int32_t mRepeatCount;
        nsecs_t mDownTime; //专指按下时间
        nsecs_t mEventTime; //事件发生时间(包括down/up等事件)
}

4.4.2 MotionEvent

class MotionEvent : public InputEvent {
    ......
    protected:
        int32_t mAction;
        int32_t mActionButton;
        int32_t mFlags;
        int32_t mEdgeFlags;
        int32_t mMetaState;
        int32_t mButtonState;
        float mXOffset;
        float mYOffset;
        float mXPrecision;
        float mYPrecision;
        nsecs_t mDownTime; //按下时间
        Vector<PointerProperties> mPointerProperties;
        Vector<nsecs_t> mSampleEventTimes;
        Vector<PointerCoords> mSamplePointerCoords;
    };
}

4.5 InputListener.h

4.5.1 NotifyKeyArgs

struct NotifyKeyArgs : public NotifyArgs {
    int32_t deviceId;
    uint32_t source;
    uint32_t policyFlags;
    int32_t action;
    int32_t flags;
    int32_t keyCode;
    int32_t scanCode;
    int32_t metaState;
    nsecs_t downTime; //按下时间
    ......
};
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值