美文网首页
Android之input InputEventReceiver

Android之input InputEventReceiver

作者: 锄禾豆 | 来源:发表于2022-01-26 18:59 被阅读0次
    frameworks/base/core/java/android/view/InputEventReceiver.java
    frameworks/base/core/jni/android_view_InputEventReceiver.cpp
    frameworks/native/libs/input/InputTransport.cpp
    注
    7.1
    

    分析代码实现情况

    1.InputEventReceiver.java代码全貌

    public abstract class InputEventReceiver {
        private static final String TAG = "InputEventReceiver";
    
        private final CloseGuard mCloseGuard = CloseGuard.get();
    
        private long mReceiverPtr;
    
        // We keep references to the input channel and message queue objects here so that
        // they are not GC'd while the native peer of the receiver is using them.
        private InputChannel mInputChannel;
        private MessageQueue mMessageQueue;
    
        // Map from InputEvent sequence numbers to dispatcher sequence numbers.
        private final SparseIntArray mSeqMap = new SparseIntArray();
    
        private static native long nativeInit(WeakReference<InputEventReceiver> receiver,
                InputChannel inputChannel, MessageQueue messageQueue);
        private static native void nativeDispose(long receiverPtr);
        private static native void nativeFinishInputEvent(long receiverPtr, int seq, boolean handled);
        private static native boolean nativeConsumeBatchedInputEvents(long receiverPtr,
                long frameTimeNanos);
    
        /**
         * Creates an input event receiver bound to the specified input channel.
         *
         * @param inputChannel The input channel.
         * @param looper The looper to use when invoking callbacks.
         */
        public InputEventReceiver(InputChannel inputChannel, Looper looper) {
            if (inputChannel == null) {
                throw new IllegalArgumentException("inputChannel must not be null");
            }
            if (looper == null) {
                throw new IllegalArgumentException("looper must not be null");
            }
    
            mInputChannel = inputChannel;
            mMessageQueue = looper.getQueue();
            mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                    inputChannel, mMessageQueue);
    
            mCloseGuard.open("dispose");
        }
    
        @Override
        protected void finalize() throws Throwable {
            try {
                dispose(true);
            } finally {
                super.finalize();
            }
        }
    
        /**
         * Disposes the receiver.
         */
        public void dispose() {
            dispose(false);
        }
    
        private void dispose(boolean finalized) {
            if (mCloseGuard != null) {
                if (finalized) {
                    mCloseGuard.warnIfOpen();
                }
                mCloseGuard.close();
            }
    
            if (mReceiverPtr != 0) {
                nativeDispose(mReceiverPtr);
                mReceiverPtr = 0;
            }
            mInputChannel = null;
            mMessageQueue = null;
        }
    
        /**
         * Called when an input event is received.
         * The recipient should process the input event and then call {@link #finishInputEvent}
         * to indicate whether the event was handled.  No new input events will be received
         * until {@link #finishInputEvent} is called.
         *
         * @param event The input event that was received.
         */
        public void onInputEvent(InputEvent event) {
            finishInputEvent(event, false);
        }
    
        ···
    
        /**
         * Finishes an input event and indicates whether it was handled.
         * Must be called on the same Looper thread to which the receiver is attached.
         *
         * @param event The input event that was finished.
         * @param handled True if the event was handled.
         */
        public final void finishInputEvent(InputEvent event, boolean handled) {
            if (event == null) {
                throw new IllegalArgumentException("event must not be null");
            }
            if (mReceiverPtr == 0) {
                Log.w(TAG, "Attempted to finish an input event but the input event "
                        + "receiver has already been disposed.");
            } else {
                int index = mSeqMap.indexOfKey(event.getSequenceNumber());
                if (index < 0) {
                    Log.w(TAG, "Attempted to finish an input event that is not in progress.");
                } else {
                    int seq = mSeqMap.valueAt(index);
                    mSeqMap.removeAt(index);
                    nativeFinishInputEvent(mReceiverPtr, seq, handled);
                }
            }
            event.recycleIfNeededAfterDispatch();
        }
    
        ···
    
        // Called from native code.
        @SuppressWarnings("unused")
        private void dispatchInputEvent(int seq, InputEvent event) {
            mSeqMap.put(event.getSequenceNumber(), seq);
            onInputEvent(event);
        }
    
        // Called from native code.
        @SuppressWarnings("unused")
        private void dispatchBatchedInputEventPending() {
            onBatchedInputEventPending();
        }
    
        public static interface Factory {
            public InputEventReceiver createInputEventReceiver(
                    InputChannel inputChannel, Looper looper);
        }
    }
    

    1.分析构造函数

        public InputEventReceiver(InputChannel inputChannel, Looper looper) {
            ···
            mInputChannel = inputChannel;
            mMessageQueue = looper.getQueue();
            mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
                    inputChannel, mMessageQueue);
    
            mCloseGuard.open("dispose");
        }
    

    将InputChannel对象传递到nativeInit

    2.native层的nativeInit实现

    android_view_InputEventReceiver.cpp
    static jlong nativeInit(JNIEnv* env, jclass clazz, jobject receiverWeak,
            jobject inputChannelObj, jobject messageQueueObj) {
        //获取native层的InputChannel对象
        sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
                inputChannelObj);
        ···
        //将InputChannel传进NativeInputEventReceiver
        sp<NativeInputEventReceiver> receiver = new NativeInputEventReceiver(env,
                receiverWeak, inputChannel, messageQueue);
        status_t status = receiver->initialize();
        if (status) {
            String8 message;
            message.appendFormat("Failed to initialize input event receiver.  status=%d", status);
            jniThrowRuntimeException(env, message.string());
            return 0;
        }
    
        //native层和java层绑定在一起
        receiver->incStrong(gInputEventReceiverClassInfo.clazz); // retain a reference for the object
        return reinterpret_cast<jlong>(receiver.get());
    }
    

    这里主要引出NativeInputEventReceiver

    3.分析NativeInputEventReceiver

    NativeInputEventReceiver::NativeInputEventReceiver(JNIEnv* env,
            jobject receiverWeak, const sp<InputChannel>& inputChannel,
            const sp<MessageQueue>& messageQueue) :
            mReceiverWeakGlobal(env->NewGlobalRef(receiverWeak)),
            mInputConsumer(inputChannel), mMessageQueue(messageQueue),
            mBatchedInputEventPending(false), mFdEvents(0) {
        if (kDebugDispatchCycle) {
            ALOGD("channel '%s' ~ Initializing input event receiver.", getInputChannelName());
        }
    }
    
    status_t NativeInputEventReceiver::initialize() {
        setFdEvents(ALOOPER_EVENT_INPUT);
        return OK;
    }
    
    void NativeInputEventReceiver::setFdEvents(int events) {
        if (mFdEvents != events) {
            mFdEvents = events;
            //从InputConsumer中获取InputChannel的fd
            int fd = mInputConsumer.getChannel()->getFd();
            if (events) {
                //把fd导入到消息队列中
                mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);
            } else {
                mMessageQueue->getLooper()->removeFd(fd);
            }
        }
    }
    

    (1)将InputChannel与InputConsumer绑定在一起,这样业务的处理,由InputConsumer代劳
    (2)将InputChannel中的fd导入消息队列,由消息队列管控

    4.分析InputConsumer

    InputTransport.cpp
    InputConsumer::InputConsumer(const sp<InputChannel>& channel) :
            mResampleTouch(isTouchResamplingEnabled()),
            mChannel(channel), mMsgDeferred(false) {
    }
    
    status_t InputConsumer::consume(InputEventFactoryInterface* factory,
            bool consumeBatches, nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
        ···
        while (!*outEvent) {
            if (mMsgDeferred) {
                // mMsg contains a valid input message from the previous call to consume
                // that has not yet been processed.
                mMsgDeferred = false;
            } else {
                // Receive a fresh message.
                status_t result = mChannel->receiveMessage(&mMsg);
                ···
        return OK;
    }
    
    
    status_t InputChannel::receiveMessage(InputMessage* msg) {
        ssize_t nRead;
        do {
            nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
        } while (nRead == -1 && errno == EINTR);
        ···
        return OK;
    }
    

    通过socket接收信息

    总结

    1.InputEventReceiver的接收消息,真正实现者是InputConsumer,因为它控制的InputChannel
    
    2.此时,InputEventReceiver就是一个socket客户端,InputConsumer负责监听服务端的数据,从而分发到InputEventReceiver.dispatchInputEvent
    

    相关文章

      网友评论

          本文标题:Android之input InputEventReceiver

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