Android 源码解析

400 阅读4分钟

input概论

InputManager实现BnInputFlinger,是一个Binder服务,有三个方法

setInputWindows registerInputChannel unregisterInputChannel

class InputManager : public InputManagerInterface,
	public BnInputFlinger {
        
class BnInputFlinger : public BnInterface<IInputFlinger> 
    
class IInputFlinger : public IInterface {
public:
    DECLARE_META_INTERFACE(InputFlinger)
    virtual void setInputWindows(const std::vector<InputWindowInfo>& inputHandles,
            const sp<ISetInputWindowsListener>& setInputWindowsListener) = 0;
    virtual void registerInputChannel(const sp<InputChannel>& channel) = 0;
    virtual void unregisterInputChannel(const sp<InputChannel>& channel) = 0;

部分数据结构解读

class InputWindowHandle : public RefBase {
    InputWindowInfo mInfo;

    sp<IBinder> getToken() const;
    sp<IBinder> getApplicationToken() {
        return mInfo.applicationInfo.token;
    }
  
/*
 * Describes the properties of a window that can receive input.
 */
struct InputWindowInfo {
    sp<IBinder> token;
    /*
     * This is filled in by the WM relative to the frame and then translated
     * to absolute coordinates by SurfaceFlinger once the frame is computed.
     */
    Region touchableRegion;
    bool visible = false;
    bool canReceiveKeys = false;
    bool hasFocus = false;
    bool hasWallpaper = false;
    bool paused = false;
    int32_t ownerPid = -1;
    int32_t ownerUid = -1;

InputApplicationInfo applicationInfo;
bool isTrustedOverlay() const;
class InputApplicationHandle : public RefBase {
InputApplicationInfo mInfo;

struct InputApplicationInfo {
    sp<IBinder> token;

在socket 读写的数据结构

struct InputMessage {
    enum class Type : uint32_t {
        KEY,
        MOTION,
        FINISHED,
        FOCUS,
    };
    struct Header {
    union Body {

InputChannel,这是个本地socket,可跨进程读写,管理fd,使用move移动语义,openInputChannelPair创建两个socket。

read: receiveMessage。read是通过Looper监听可读

write: sendMessage。write是阻塞write

[0]是server端,在wm进程

[1]是client端,通过Binder驱动,将该套接字移到应用进程(跨进城传递)

// a local unix domain socket
class InputChannel : public RefBase {
    static sp<InputChannel> create(const std::string& name,
                                   android::base::unique_fd fd,
                                   sp<IBinder> token);
static status_t openInputChannelPair(const std::string& name,
        sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);

    status_t sendMessage(const InputMessage* msg);
    status_t receiveMessage(InputMessage* msg);

    // two different (client and server) input channels will share the
    // same connection token.
    sp<IBinder> getConnectionToken() const;

    android::base::unique_fd mFd;

    sp<IBinder> mToken;

token 是BBinder。server注册到InputDispatcher,client注册到应用进程的InputEventReceiver。

token在client便是一个句柄,client通过句柄,server便能找到与其对应的server

if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
    sp<IBinder> token = new BBinder();

    std::string serverChannelName = name + " (server)";
    android::base::unique_fd serverFd(sockets[0]);
    outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd), token);

    std::string clientChannelName = name + " (client)";
    android::base::unique_fd clientFd(sockets[1]);
    outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd), token);

生产者,将事件放入channel

生产者生产事件后,消费者消费事件后,需要通知该事件的消费情况

InputPublisher
    
publishKeyEvent
status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled);

InputConsumer
consume
sendFinishedSignal

Connection 管理channel,这个是wm具有的语义,client没有。

outboundQueue输出事件队列,需要往channel写

waitQueue 等待确认的队列

/* Manages the dispatch state associated with a single input channel. */
class Connection : public RefBase {
        sp<InputChannel> inputChannel; // never null
        InputPublisher inputPublisher;
        bool responsive = true;
    
    // Queue of events that need to be published to the connection.
    std::deque<DispatchEntry*> outboundQueue;

    // Queue of events that have been published to the connection but that have not
    // yet received a "finished" response from the application.
    std::deque<DispatchEntry*> waitQueue;

Reader和Dispatcher结构解读

InputReader是监听系统事件,单独线程,有Looper。

其他对象可往Looper入列function,选择性wakeUp。

Reader负责监听事件,不派发事件。Reader在mLock锁外调用监听者,将已发生的读写事件入队(这里没有阻塞),然后继续poll

事件派发由Dispatcher负责。如果Reader既负责监听,也负责派发,处理流程过程,若不能及早回到poll,便会错过已发生的可读写事件,有延时。

Dispatcher负责派发事件,Dispatcher作为一个监听者,注册到Reader中。Dispatcher对事件加工,封装,选择channel(焦点窗口),sendMessage

事件的的接收者是InputEventReceiver

class InputReader : public InputReaderInterface {
public:
    InputReader(std::shared_ptr<EventHubInterface> eventHub,
                const sp<InputReaderPolicyInterface>& policy,
                const sp<InputListenerInterface>& listener);
    void loopOnce();

    std::unique_ptr<InputThread> mThread;

    Mutex mLock;

sp<QueuedInputListener> mQueuedListener;
/*
 * The interface used by the InputReader to notify the InputListener about input events.
 */
class InputListenerInterface : public virtual RefBase {
protected:
    InputListenerInterface() { }
    virtual ~InputListenerInterface() { }

public:
    virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) = 0;
    virtual void notifyKey(const NotifyKeyArgs* args) = 0;
    virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
    virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
    virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
};

class QueuedInputListener : public InputListenerInterface {
    sp<InputListenerInterface> mInnerListener;
    std::vector<NotifyArgs*> mArgsQueue;

args->notify(mInnerListener) ---> mInnerListener.notifyKey(this)

两个类相互引用,故这里没有考虑智能指针生命周期,而是事件通知完成后,直接delete。事件是一次性的。

void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);
        delete args;
    }
    mArgsQueue.clear();
}

Reader调用到这里,事件入队,唤醒Dispatcher,让其对事件加工,派发

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    KeyEvent event;
    event.initialize(...);

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

        KeyEntry* newEntry = new KeyEntry(
        needWake = enqueueInboundEventLocked(newEntry);
        mLock.unlock();
    } // release lock

    if (needWake) {
        mLooper->wake();
    }
}

registerInputChannel,线程安全的,可在任意线程调用(函数内部用锁入队,唤醒处理事件)

先根据创建Channel时的token判断当前Channel是否已注册

未注册,创建一个Connection管理Channel,并添加到两个队列mConnectionsByFd,mInputChannelsByToken

一个是关于连接的,一个是关于Channel的

status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel) {

    { // acquire lock
        std::scoped_lock _l(mLock);
        sp<Connection> existingConnection = getConnectionLocked(inputChannel->getConnectionToken());
        if (existingConnection != nullptr) {
            ALOGW("Attempted to register already registered input channel '%s'",
                  inputChannel->getName().c_str());
            return BAD_VALUE;
        }

        sp<Connection> connection = new Connection(inputChannel, false /*monitor*/, mIdGenerator);

        int fd = inputChannel->getFd();
        mConnectionsByFd[fd] = connection;
        mInputChannelsByToken[inputChannel->getConnectionToken()] = inputChannel;

        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
    } // release lock

    // Wake the looper because some connections have changed.
    mLooper->wake();
    return OK;
}

Activity表示一个应用窗口。窗口抽象是Window,其具体实现是PhoneWindow,Activity实现Window的Callback。

PhoneWindow并有一个DecorView(控制Activity最外层的UI视效),DecorView应用视图的根,ViewRootImpl负责绘制和应用派发事件