91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android事件分發中事件是怎么來的

發布時間:2023-03-15 11:40:48 來源:億速云 閱讀:148 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“Android事件分發中事件是怎么來的”,內容詳細,步驟清晰,細節處理妥當,希望這篇“Android事件分發中事件是怎么來的”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

Andriod事件分發的事件從何而來

注冊事件回調是通過mWindowSession.addToDisplayAsUser來實現的,這是一個Binder調用實際調用的是frameworks/base/services/core/java/com/android/server/wm/Session.java這個類。

 //frameworks/base/services/core/java/com/android/server/wm/Session.java 
  @Override
    public int addToDisplayAsUser(IWindow window, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, int userId, InsetsVisibilities requestedVisibilities,
            InputChannel outInputChannel, InsetsState outInsetsState,
            InsetsSourceControl[] outActiveControls, Rect outAttachedFrame,
            float[] outSizeCompatScale) {
        return mService.addWindow(this, window, attrs, viewVisibility, displayId, userId,
                requestedVisibilities, outInputChannel, outInsetsState, outActiveControls,
                outAttachedFrame, outSizeCompatScale);
    }

這里的mService就是WMS.調用的就是WMS的addWindow,addWindow方法很長,其中與事件相關的就兩行

//frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
......           
  final WindowState win = new WindowState(this, session, client, token, parentWindow,appOp[0], attrs, viewVisibility, session.mUid, userId,session.mCanAddInternalSystemWindow);
  win.openInputChannel(outInputChannel);
//frameworks/base/services/core/java/com/android/server/wm/WindowState.java
void openInputChannel(InputChannel outInputChannel) {
        if (mInputChannel != null) {
            throw new IllegalStateException("Window already has an input channel.");
        }
        String name = getName();
        mInputChannel = mWmService.mInputManager.createInputChannel(name);
        mInputChannelToken = mInputChannel.getToken();
        mInputWindowHandle.setToken(mInputChannelToken);
        mWmService.mInputToWindowMap.put(mInputChannelToken, this);
        if (outInputChannel != null) {
          //將native創建的InputChannel復制給參數outInputChannel
            mInputChannel.copyTo(outInputChannel);
        } else {
            // If the window died visible, we setup a fake input channel, so that taps
            // can still detected by input monitor channel, and we can relaunch the app.
            // Create fake event receiver that simply reports all events as handled.
            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mInputChannel);
        }
    }

調用WMS中的成員mInputManager

調用了WMS中的成員mInputManager來注冊了InputChannel,mInputManager是一個InputManagerService。

這下就對了,事件從InputManagerService中來很合理。

    public InputChannel createInputChannel(String name) {
        return mNative.createInputChannel(name);
    }

調用的mNative的方法

這個對象是在InputManagerService創建的時候初始化的

    public InputManagerService(Context context) {
        this(new Injector(context, DisplayThread.get().getLooper()));
    }

    @VisibleForTesting
    InputManagerService(Injector injector) {
        // The static association map is accessed by both java and native code, so it must be
        // initialized before initializing the native service.
        mStaticAssociations = loadStaticInputPortAssociations();

        mContext = injector.getContext();
        mHandler = new InputManagerHandler(injector.getLooper());
        mNative = injector.getNativeService(this);
      ....
    }
//frameworks/base/services/core/java/com/android/server/input/NativeInputManagerService.java
       NativeInputManagerService getNativeService(InputManagerService service) {
            return new NativeInputManagerService.NativeImpl(service, mContext, mLooper.getQueue());
        }

最終返回的是一個NativeImpl實例。字面意思就知道了,這是一個Native方法的實現,createInputChannel來到了native層。

//frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputChannel(
        const std::string& name) {
    ATRACE_CALL();
    return mInputManager->getDispatcher().createInputChannel(name);
}

調用了mInputManager的getDispatcher函數看名字就知道應該有個變量mDispatcher,查看mInputManager是怎么創建的可以發現是在NativeInputManager創建的時候初始化的

    InputManager* im = new InputManager(this, this);
    mInputManager = im;

看看InputManager怎么初始化

InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
    mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
    mReader = createInputReader(readerPolicy, *mBlocker);
}

這里就出現了重要的兩個類InputDispatcherInputReader,createInputChanne方法l最終調用到了InputDispatcher中的createInputChannel。

//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
    if (DEBUG_CHANNEL_CREATION) {
        ALOGD("channel '%s' ~ createInputChannel", name.c_str());
    }
    std::unique_ptr<InputChannel> serverChannel;
    std::unique_ptr<InputChannel> clientChannel;
  	//調用創建了一個serverChannel和一個clientChannel
    status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
    if (result) {
        return base::Error(result) << "Failed to open input channel pair with name " << name;
    }
    { // acquire lock
        std::scoped_lock _l(mLock);
        const sp<IBinder>& token = serverChannel->getConnectionToken();
        int fd = serverChannel->getFd();
        sp<Connection> connection =
                new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);
        if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
            ALOGE("Created a new connection, but the token %p is already known", token.get());
        }
        mConnectionsByToken.emplace(token, connection);
        std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
                                                            this, std::placeholders::_1, token);
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
    } // release lock
    // Wake the looper because some connections have changed.
    mLooper->wake();
    return clientChannel;
}

createInputChannel干了3件事

  • 首先使用openInputChannelPair創建了2個InputChannel,一個clientChannel和一個serverChannel

  • 將serverChannel封裝成connection,并放入成員變量mConnectionsByToken中管理,這樣在事件到來的時候就可以使用connection向客戶端發送事件了

  • 利用Looper持續監聽serverChannel,事件處理的回調消息會就到InputDispatcher::handleReceiveCallback回調,最后把clientChannel返回給客戶端,也就是最初在WMS中得到的InputChannel。

首先看下openInputChannelPair

//frameworks/native/libs/input/InputTransport.cpp
status_t InputChannel::openInputChannelPair(const std::string& name,
                                            std::unique_ptr<InputChannel>& outServerChannel,
                                            std::unique_ptr<InputChannel>& outClientChannel) {
    int sockets[2];
  	//真正創建了socket
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
        status_t result = -errno;
        ALOGE("channel '%s' ~ Could not create socket pair.  errno=%s(%d)", name.c_str(),
              strerror(errno), errno);
        outServerChannel.reset();
        outClientChannel.reset();
        return result;
    }
	//設置了socket傳輸的大小為32k
    int bufferSize = SOCKET_BUFFER_SIZE;
    setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
    setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
    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);
    return OK;
}

熟悉Linux的話就知道socketpair創建了一對雙向的socket,往socket[0]中寫能從socket[1]讀,反向也是一樣,分別創建了outServerChannel和outClientChannel,兩個InputChannel有著同一個BBinder作為token。

回到createInputChannel中

 const sp<IBinder>& token = serverChannel->getConnectionToken();
        int fd = serverChannel->getFd();//拿到socket fd
        sp<Connection> connection =
                new Connection(std::move(serverChannel), false /*monitor*/, mIdGenerator);
        if (mConnectionsByToken.find(token) != mConnectionsByToken.end()) {
            ALOGE("Created a new connection, but the token %p is already known", token.get());
        }
        mConnectionsByToken.emplace(token, connection);
 std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
                                                            this, std::placeholders::_1, token);
        mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);

這里將創建的serverChannel封裝成了connection,同時用token作為key,存到了mConnectionsByToken中,這樣就可以利用token來快速找到serverChannel封裝的connection。最后監聽serverChannel的fd,有事件時回調給InputDispatcher::handleReceiveCallback方法的最后把創建的clientChannel返回給了客戶端,就是開頭的WMS中。這樣在WMS就也能通過clientChannel來獲取事件了。

讀到這里,這篇“Android事件分發中事件是怎么來的”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

诸暨市| 永寿县| 古蔺县| 余庆县| 南澳县| 安多县| 孝昌县| 宣城市| 武陟县| 万荣县| 福海县| 南澳县| 吴旗县| 丹凤县| 汉川市| 昌邑市| 乌兰浩特市| 武安市| 雷山县| 潜江市| 大渡口区| 廊坊市| 仁化县| 景泰县| 德州市| 股票| 莎车县| 清苑县| 吉安县| 常宁市| 郸城县| 九江县| 上栗县| 梅河口市| 进贤县| 黄浦区| 东辽县| 平安县| 鹿邑县| 呼和浩特市| 巴林左旗|