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负责绘制和应用派发事件