Android Input 流程分析
作者:互联网
1. addView 流程
addView()一般用来动态添加View,LinearLayout、RelativeLayout 添加子控件都可以用addView()
addView 最终在WindowManager -> WindowManagerImpl ->WindowManagerGlobal -> ViewRootImpl.setView()
OnCreated阶段:
frameworks/base/core/java/android/app/Activity.java
final void attach(Context context, ActivityThread aThread,){
mWindow = new PhoneWindow(this, window, activityConfigCallback);
}
public Window getWindow() {
return mWindow;
}
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
private LayoutInflater mLayoutInflater;
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
}
// 首次setContentView会创建DecorView,调用mLayoutInflater.inflate,把resId文件映射成各种view
frameworks/base/core/java/android/view/LayoutInflater.java
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
return inflate(resource, root, root != null);
}
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot){
View result = root;
root.addView(temp, params);
}
frameworks/base/core/java/com/android/internal/policy/DecorView.java
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {}
//public class FrameLayout extends ViewGroup {}
frameworks/base/core/java/android/view/ViewGroup.java
public void addView(View child, LayoutParams params) {
addView(child, -1, params);
}
public void addView(View child, int index, LayoutParams params) {
requestLayout();
invalidate(true);
// addViewInner 主要是把子view添加到childViews数组中
addViewInner(child, index, params, false);
}
OnResume阶段:
frameworks/base/core/java/android/app/ActivityThread.java
@Override
public void handleResumeActivity(){
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
r.activity.makeVisible();
}
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
// WindowManager.addView()
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
frameworks/base/core/java/android/view/ViewManager.java
public interface ViewManager{
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
}
frameworks/base/core/java/android/view/WindowManager.java
public interface WindowManager extends ViewManager {
}
frameworks/base/core/java/android/view/WindowManagerImpl.java
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
}
frameworks/base/core/java/android/view/WindowManagerGlobal.java
public final class WindowManagerGlobal {
private static WindowManagerGlobal sDefaultWindowManager;
public static WindowManagerGlobal getInstance() {
if (sDefaultWindowManager == null) {
sDefaultWindowManager = new WindowManagerGlobal();
}
return sDefaultWindowManager;
}
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
ViewRootImpl root;
root = new ViewRootImpl(view.getContext(), display);
root.setView(view, wparams, panelParentView);
}
}
setView 时 new InputChannel(),作为参数传入到 Session中。ViewRootImpl.setView() -> Session.addToDisplay() -> WindowManagerService.addWindow() -> WinState.openInputChannel(outInputChannel)
frameworks/base/core/java/android/view/ViewRootImpl.java
final IWindowSession mWindowSession;
InputChannel mInputChannel;
WindowInputEventReceiver mInputEventReceiver;
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
requestLayout();
if ((mWindowAttributes.inputFeatures
& WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
mInputChannel = new InputChannel();
}
//通过Binder调用,进入system进程的Session,这里将客户端的InputChannel对象作为参数传入
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
if (mInputChannel != null) {
mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
Looper.myLooper());
}
}
frameworks/base/services/core/java/com/android/server/wm/Session.java
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
final WindowManagerService mService;
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}
}
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
public int addWindow(Session session, IWindow client, int seq,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
final boolean openInputChannels = (outInputChannel != null
&& (attrs.inputFeatures & INPUT_FEATURE_NO_INPUT_CHANNEL) == 0);
if (openInputChannels) {
win.openInputChannel(outInputChannel);
}
}
frameworks/base/services/core/java/com/android/server/wm/WindowState.java
void openInputChannel(InputChannel outInputChannel) {
String name = getName();
// 返回两个 InputChannel, 0 通过 mService.mInputManager.registerInputChannel 注册
// 1 通过 transferTo 给 outInputChannel
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mInputWindowHandle.inputChannel = inputChannels[0];
if (outInputChannel != null) {
mClientChannel.transferTo(outInputChannel);
mClientChannel.dispose();
}
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}
frameworks/base/core/java/android/view/InputChannel.java
public void transferTo(InputChannel outParameter) {
nativeTransferTo(outParameter);
}
frameworks/base/core/jni/android_view_InputChannel.cpp
static const JNINativeMethod gInputChannelMethods[] = {
{ "nativeTransferTo", "(Landroid/view/InputChannel;)V",
(void*)android_view_InputChannel_nativeTransferTo },
}
static void android_view_InputChannel_nativeTransferTo(JNIEnv* env, jobject obj,
jobject otherObj) {
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
android_view_InputChannel_setNativeInputChannel(env, otherObj, nativeInputChannel);
android_view_InputChannel_setNativeInputChannel(env, obj, NULL);
}
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputChannel monitorInput(String inputChannelName) {
// channelPair[0] -> serverChannel, channelPair[1] -> clientChannel,实际 native 返回
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
//重要!!! 传入inputChannels[0] 即 serverChannel
nativeRegisterInputChannel(mPtr, inputChannels[0], null, true);
return inputChannels[1];
}
public void registerInputChannel(InputChannel inputChannel,
InputWindowHandle inputWindowHandle) {
nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}
public InputManagerService(Context context) {
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
}
public void start() {
nativeStart(mPtr);
}
frameworks/base/core/java/android/view/InputChannel.java
public static InputChannel[] openInputChannelPair(String name) {
return nativeOpenInputChannelPair(name);
}
2. OpenInputChannelPair&nativeRegisterInputChannel
图片从 Android输入系统之InputChannel(上)_区块链斜杠青年(爱踢门)-CSDN博客 拷贝过来
frameworks/base/core/jni/android_view_InputChannel.cpp
OpenInputChannelPair:
static const JNINativeMethod gInputChannelMethods[] = {
{ "nativeOpenInputChannelPair", "(Ljava/lang/String;)[Landroid/view/InputChannel;",
(void*)android_view_InputChannel_nativeOpenInputChannelPair },
}
// channelPair[0] -> serverChannel, channelPair[1] -> clientChannel
static jobjectArray android_view_InputChannel_nativeOpenInputChannelPair(){
sp<InputChannel> serverChannel;
sp<InputChannel> clientChannel;
// frameworks/native/libs/input/InputTransport.cpp 中创建sockets
// serverChannel -> name + " (server)", clientChannel -> name + " (client)";
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
jobjectArray channelPair = env->NewObjectArray(2, gInputChannelClassInfo.clazz, NULL);
jobject serverChannelObj = android_view_InputChannel_createInputChannel(env,
std::make_unique<NativeInputChannel>(serverChannel));
jobject clientChannelObj = android_view_InputChannel_createInputChannel(env,
std::make_unique<NativeInputChannel>(clientChannel));
env->SetObjectArrayElement(channelPair, 0, serverChannelObj);
env->SetObjectArrayElement(channelPair, 1, clientChannelObj);
return channelPair;
}
static jobject android_view_InputChannel_createInputChannel(){
android_view_InputChannel_setNativeInputChannel(env, inputChannelObj,
nativeInputChannel.release());
return inputChannelObj;
}
static void android_view_InputChannel_setNativeInputChannel(JNIEnv* env, jobject inputChannelObj,
NativeInputChannel* nativeInputChannel) {
env->SetLongField(inputChannelObj, gInputChannelClassInfo.mPtr,
reinterpret_cast<jlong>(nativeInputChannel));
}
nativeInit/nativeStart/nativeRegisterInputChannel:
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static const JNINativeMethod gInputManagerMethods[] = {
{ "nativeInit",
"(Lcom/android/server/input/InputManagerService;Landroid/content/Context;Landroid/os/MessageQueue;)J",
(void*) nativeInit },
{ "nativeStart", "(J)V",
(void*) nativeStart },
{ "nativeRegisterInputChannel",
"(JLandroid/view/InputChannel;Lcom/android/server/input/InputWindowHandle;Z)V",
(void*) nativeRegisterInputChannel },
}
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,jlong ptr,
jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor){
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
sp<InputWindowHandle> inputWindowHandle =
android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);
status_t status = im->registerInputChannel(
env, inputChannel, inputWindowHandle, monitor);
}
status_t NativeInputManager::registerInputChannel(JNIEnv* /* env */,
const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
ATRACE_CALL();
return mInputManager->getDispatcher()->registerInputChannel(
inputChannel, inputWindowHandle, monitor);
}
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
}
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
status_t result = im->getInputManager()->start();
}
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
JNIEnv* env = jniEnv();
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
frameworks/native/services/inputflinger/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);
}
system/core/libutils/include/utils/Thread.h
class Thread : virtual public RefBase {
// Start the thread in threadLoop() which needs to be implemented.
virtual status_t run( const char* name,
int32_t priority = PRIORITY_DEFAULT,
size_t stack = 0);
virtual bool threadLoop() = 0;
}
system/core/libutils/Threads.cpp
//所以 xxxThread->run() 会调到其对应的 threadLoop()方法中
status_t Thread::run(const char* name, int32_t priority, size_t stack) {
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
}
int Thread::_threadLoop(void* user) {
Thread* const self = static_cast<Thread*>(user);
do {
result = self->threadLoop();
}
}
3. InputDispatcher
InputDispatcher:
frameworks/native/services/inputflinger/InputDispatcher.h
class InputDispatcherThread : public Thread {
private:
virtual bool threadLoop();
sp<InputDispatcherInterface> mDispatcher;
}
class InputDispatcher : public InputDispatcherInterface {
class Connection : public RefBase {
// Queue of events that need to be published to the connection.
Queue<DispatchEntry> outboundQueue;
}
EventEntry* mPendingEvent;
Queue<EventEntry> mInboundQueue;
Queue<EventEntry> mRecentQueue;
Queue<CommandEntry> mCommandQueue;
}
frameworks/native/services/inputflinger/InputDispatcher.cpp
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
int fd = inputChannel->getFd();
mConnectionsByFd.add(fd, connection);
if (monitor) {
mMonitoringChannels.push(inputChannel);
}
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
}
class Connection : public RefBase {
public:
sp<InputChannel> inputChannel;
sp<InputWindowHandle> inputWindowHandle;
InputPublisher inputPublisher;
}
InputDispatcher::Connection::Connection(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) :
status(STATUS_NORMAL), inputChannel(inputChannel), inputWindowHandle(inputWindowHandle),
monitor(monitor),
inputPublisher(inputChannel), inputPublisherBlocked(false) {
}
InputDispatcher::InputDispatcher(const sp<InputDispatcherPolicyInterface>& policy)
: mDispatchEnabled(false), mDispatchFrozen(false), mInputFilterEnabled(false){
mLooper = new Looper(false);
}
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
void InputDispatcher::dispatchOnce() {
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime);
}
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
mLooper->pollOnce(timeoutMillis);
}
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
mPendingEvent = mInboundQueue.dequeueAtHead();
switch (mPendingEvent->type) {
case EventEntry::TYPE_KEY: {
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::TYPE_MOTION: {
done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
}
if (done) {
releasePendingEventLocked();
}
}
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
Vector<InputTarget> inputTargets;
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
setInjectionResultLocked(entry, injectionResult);
addMonitoringTargetsLocked(inputTargets);
dispatchEventLocked(currentTime, entry, inputTargets);
}
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector<InputTarget>& inputTargets) {
pokeUserActivityLocked(eventEntry);
for (size_t i = 0; i < inputTargets.size(); i++) {
const InputTarget& inputTarget = inputTargets.itemAt(i);
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
if (connectionIndex >= 0) {
sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
}
}
}
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,xxx){
if (inputTarget->flags & InputTarget::FLAG_SPLIT) {
enqueueDispatchEntriesLocked(currentTime, connection,
splitMotionEntry, inputTarget);
}
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,xxx){
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
if (wasEmpty && !connection->outboundQueue.isEmpty()) {
startDispatchCycleLocked(currentTime, connection);
}
}
void InputDispatcher::enqueueDispatchEntryLocked(){
DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, // increments ref
inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset,
inputTarget->scaleFactor);
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
dispatchEntry->resolvedAction = keyEntry->action;
dispatchEntry->resolvedFlags = keyEntry->flags;
break;
}
// Enqueue the dispatch entry.
connection->outboundQueue.enqueueAtTail(dispatchEntry);
traceOutboundQueueLengthLocked(connection);
}
void InputDispatcher::startDispatchCycleLocked(){
while (connection->status == Connection::STATUS_NORMAL
&& !connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.head;
dispatchEntry->deliveryTime = currentTime;
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
keyEntry->deviceId, keyEntry->source,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
keyEntry->keyCode, keyEntry->scanCode,
keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
keyEntry->eventTime);
}
}
}
}
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
KeyEvent event;
event.initialize(args->deviceId, args->source, args->action,
flags, keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
KeyEntry* newEntry = new KeyEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, flags, keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
needWake = enqueueInboundEventLocked(newEntry);
if (needWake) {
mLooper->wake();// 唤醒 InputReader
}
}
// 通过 jni 调到 java 层,其实就是PhoneWindowManager先做一次事件拦截处理操作
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
uint32_t& policyFlags) {
JNIEnv* env = jniEnv();
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeQueueing,
keyEventObj, policyFlags);
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
}
//这里将keyArgs转换成KeyEntery这种数据封装,并添加到InputDispatcher的mInboundQueue里,最后唤醒InputDispacher线程
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
mInboundQueue.enqueueAtTail(entry);
switch (entry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(entry);
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast<MotionEntry*>(entry);
}
return needWake;
}
frameworks/native/libs/input/InputTransport.cpp
status_t InputChannel::openInputChannelPair(const std::string& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
int sockets[2];
socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);
std::string serverChannelName = name;
serverChannelName += " (server)";
outServerChannel = new InputChannel(serverChannelName, sockets[0]);
std::string clientChannelName = name;
clientChannelName += " (client)";
outClientChannel = new InputChannel(clientChannelName, sockets[1]);
}
// 在 InputDispatcher 中 new Connection() 构造 InputPublisher 对象
InputPublisher::InputPublisher(const sp<InputChannel>& channel) : mChannel(channel) {}
status_t InputPublisher::publishKeyEvent(){
InputMessage msg;
msg.header.type = InputMessage::TYPE_KEY;
msg.body.key.seq = seq;
msg.body.key.deviceId = deviceId;
msg.body.key.keyCode = keyCode;
msg.body.key.scanCode = scanCode;
return mChannel->sendMessage(&msg);
}
status_t InputPublisher::publishMotionEvent(){
InputMessage msg;
msg.header.type = InputMessage::TYPE_MOTION;
return mChannel->sendMessage(&msg);
}
// 建立两个channel, 用来通信,我们这里的inputdispatch相当于一个channel用来分发事件,
// 还有一个通来接收,在android_view_InputEventReceiver.cpp中
status_t InputChannel::sendMessage(const InputMessage* msg) {
const size_t msgLength = msg->size();
InputMessage cleanMsg;
msg->getSanitizedCopy(&cleanMsg);
do {
nWrite = ::send(mFd, &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
}
status_t InputConsumer::consume(InputEventFactoryInterface* factory,
bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent,
int32_t* displayId) {
while (!*outEvent) {
status_t result = mChannel->receiveMessage(&mMsg);
switch (mMsg.header.type) {
case InputMessage::TYPE_KEY: {
KeyEvent* keyEvent = factory->createKeyEvent();
initializeKeyEvent(keyEvent, &mMsg);
*outSeq = mMsg.body.key.seq;
*outEvent = keyEvent;
break;
}
}
}
}
status_t InputChannel::receiveMessage(InputMessage* msg) {
do {
nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
} while (nRead == -1 && errno == EINTR);
}
4.InputReader
frameworks/native/services/inputflinger/InputReader.h
class InputReaderThread : public Thread {
sp<InputReaderInterface> mReader;
virtual bool threadLoop();
}
frameworks/native/services/inputflinger/InputReader.cpp
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);
}
void InputReader::requestTimeoutAtTimeLocked(nsecs_t when) {
if (when < mNextTimeout) {
mNextTimeout = when;
mEventHub->wake();// 调用到EventHub的 wake()方法
}
}
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
}
void InputReader::loopOnce() {
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
if (count) {
processEventsLocked(mEventBuffer, count);
}
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
mQueuedListener->flush(); // QueuedInputListener::flush() -> args->notify()
}
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
}else {
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
}
}
}
}
//DEVICE_ADDED
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
device->configure(when, &mConfig, 0);
device->reset(when);
mDevices.add(deviceId, device);
}
InputDevice* InputReader::createDeviceLocked() {
device->addMapper(new SwitchInputMapper(device));
device->addMapper(new RotaryEncoderInputMapper(device));
device->addMapper(new VibratorInputMapper(device));
device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
device->addMapper(new CursorInputMapper(device));
device->addMapper(new MultiTouchInputMapper(device));
}
void InputDevice::addMapper(InputMapper* mapper) {
mMappers.add(mapper);
}
// processEventsForDeviceLocked()
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
InputDevice* device = mDevices.valueAt(deviceIndex);
device->process(rawEvents, count);
}
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
size_t numMappers = mMappers.size();
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
mapper->process(rawEvent);
}
}
// 以KeyboardInputMapper 为例
class KeyboardInputMapper : public InputMapper {}
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY: {
int32_t scanCode = rawEvent->code;
if (isKeyboardOrGamepadKey(scanCode)) {
processKey(rawEvent->when, rawEvent->value != 0, scanCode, usageCode);
}
break;
}
case EV_MSC: {
if (rawEvent->code == MSC_SCAN) {
mCurrentHidUsage = rawEvent->value;
}
break;
}
case EV_SYN: {
if (rawEvent->code == SYN_REPORT) {
mCurrentHidUsage = 0;
}
}
}
}
void KeyboardInputMapper::processKey(){
if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, mMetaState,
&keyCode, &keyMetaState, &policyFlags))
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);
}
InputListenerInterface* InputReader::ContextImpl::getListener() {
return mReader->mQueuedListener.get();
}
frameworks/native/services/inputflinger/InputListener.cpp
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
mArgsQueue.push(new NotifyKeyArgs(*args));
}
void QueuedInputListener::flush() {
size_t count = mArgsQueue.size();
for (size_t i = 0; i < count; i++) {
NotifyArgs* args = mArgsQueue[i];
args->notify(mInnerListener);
}
}
// 以 NotifyKeyArgs 为例
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
listener->notifyKey(this);
// InputReader 构造时,mQueuedListener = new QueuedInputListener(listener), listener 为 InputDispatcher
// 所以到了 InputDispatcher 的 notifyKey 中
}
5.EventHub
frameworks/native/services/inputflinger/EventHub.cpp
EventHub::EventHub(void) :mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false), mNeedToScanDevices(true) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
mINotifyFd = inotify_init();
int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
int wakeFds[2];
result = pipe(wakeFds);
mWakeReadPipeFd = wakeFds[0];
mWakeWritePipeFd = wakeFds[1];
result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
eventItem.data.u32 = EPOLL_ID_WAKE;
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
}
void EventHub::wake() {
nWrite = write(mWakeWritePipeFd, "W", 1); //主线程,pipe[1]写入,InputReaderThread pipe[0]读取
}
// InputReaderThread 线程调用
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
for (;;) {
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
scanDevicesLocked();
}
while (mOpeningDevices != NULL) {
while (mPendingEventIndex < mPendingEventCount) {
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
if (eventItem.data.u32 == EPOLL_ID_WAKE) {
do {
// 重要 InputReadThread 读取信息
nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));
} while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));
}
Device* device = mDevices.valueAt(deviceIndex);
if (eventItem.events & EPOLLIN) {
int32_t readSize = read(device->fd, readBuffer,
sizeof(struct input_event) * capacity);
}
}
}
mLock.unlock(); // release lock before poll, must be before release_wake_lock
release_wake_lock(WAKE_LOCK_ID);
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
mPendingEventCount = size_t(pollResult);
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
}
6. 事件分发机制
Activity:
frameworks/base/core/java/android/app/Activity.java
final void attach(Context context, ActivityThread aThread,){
mWindow = new PhoneWindow(this, window, activityConfigCallback);
}
public Window getWindow() {
return mWindow;
}
public boolean dispatchTouchEvent(MotionEvent ev) {
//ACTION_DOWN事件时,如果对应activity重写该方法,则调用对应方法
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
onUserInteraction();
}
//PhoneWindow.superDispatchTouchEvent()
if (getWindow().superDispatchTouchEvent(ev)) {
return true;
}
return onTouchEvent(ev);
}
public boolean onTouchEvent(MotionEvent event) {
if (mWindow.shouldCloseOnTouch(this, event)) {
finish();
return true;
}
return false;
}
PhoneWindow:
frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
private LayoutInflater mLayoutInflater;
public boolean superDispatchTouchEvent(MotionEvent event) {
return mDecor.superDispatchTouchEvent(event);
}// private DecorView mDecor;
DecorView:
frameworks/base/core/java/com/android/internal/policy/DecorView.java
public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
public boolean superDispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
}
//public class FrameLayout extends ViewGroup {}
ViewGroup:
frameworks/base/core/java/android/view/ViewGroup.java
public boolean dispatchTouchEvent(MotionEvent ev) {
//判断窗口被遮挡,为true未遮挡继续 dispatch
if (onFilterTouchEventForSecurity(ev)) {
final int action = ev.getAction();
final int actionMasked = action & MotionEvent.ACTION_MASK;
// 初始化 down 动作,开始新的触摸手势时,放弃所有以前的状态。
// 由于应用程序切换、ANR或某些其他状态更改,框架可能已放弃上一个手势的向上或取消事件。
if (actionMasked == MotionEvent.ACTION_DOWN) {
cancelAndClearTouchTargets(ev);
resetTouchState();
}
if (actionMasked == MotionEvent.ACTION_DOWN || mFirstTouchTarget != null) {
final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
// 进行拦截处理
if (!disallowIntercept) {
intercepted = onInterceptTouchEvent(ev);
ev.setAction(action);
}
}
final View[] children = mChildren;
for (int i = childrenCount - 1; i >= 0; i--) {
if (!canViewReceivePointerEvents(child)
|| !isTransformedTouchPointInView(x, y, child, null)) {
ev.setTargetAccessibilityFocus(false);
continue;
}
resetCancelNextUpFlag(child);
if (dispatchTransformedTouchEvent(ev, false, child, idBitsToAssign))
}
}
if (mFirstTouchTarget == null) {
// No touch targets so treat this as an ordinary view.
handled = dispatchTransformedTouchEvent(ev, canceled, null,
TouchTarget.ALL_POINTER_IDS);
} else {
TouchTarget target = mFirstTouchTarget;
while (target != null) {
final TouchTarget next = target.next;
if (alreadyDispatchedToNewTouchTarget && target == newTouchTarget) {
handled = true;
}else {
if (dispatchTransformedTouchEvent(ev, cancelChild,
target.child, target.pointerIdBits)) {
handled = true;
}
}
}
}
}
private boolean dispatchTransformedTouchEvent(){
final int oldAction = event.getAction();
if (cancel || oldAction == MotionEvent.ACTION_CANCEL) {
event.setAction(MotionEvent.ACTION_CANCEL);
if (child == null) {
handled = super.dispatchTouchEvent(event);
} else {
handled = child.dispatchTouchEvent(event);
}
event.setAction(oldAction);
return handled;
}
}
View:
frameworks/base/core/java/android/view/View.java
public boolean dispatchTouchEvent(MotionEvent event) {
if (onFilterTouchEventForSecurity(event)) {
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null /*View.setOnClickListener()*/
&& (mViewFlags & ENABLED_MASK) == ENABLED /*当前控件enabled状态*/
&& li.mOnTouchListener.onTouch(this, event)) {
/*View.setOnClickListener()重写了onTouch()*/
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
return result;
}
public boolean dispatchTouchEvent(MotionEvent event) {
onTouchEvent(event);
}
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_UP:
mPerformClick = new PerformClick();
break;
}
}
private final class PerformClick implements Runnable {
@Override
public void run() {
performClickInternal();
}
}
private boolean performClickInternal() {
notifyAutofillManagerOnClick();
return performClick();
}
public boolean performClick() {
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
//在Button/TextView/Layout等 setOnClickListener(new View.OnClickListener(){})传入
public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
ListenerInfo getListenerInfo() {
mListenerInfo = new ListenerInfo();
return mListenerInfo;
}
标签:InputChannel,android,java,void,public,Input,Android,流程,view 来源: https://blog.csdn.net/SHK242673/article/details/122595605