最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

systemserver的inputdispatcher直接產(chǎn)生CANCEL事件原理分析-討厭的android觸摸面試題

2023-09-11 09:48 作者:千里馬學(xué)框架  | 我要投稿

背景回顧:

上一個blog已經(jīng)重點講解了app層面自己產(chǎn)生的Cancel觸摸事件,大概產(chǎn)生的原理如下:

在這里插入圖片描述

即可以看出來,再服務(wù)端systemserver其實傳遞的觸摸事件依然是move,只是move事件到了app端后,由于app端自己的業(yè)務(wù)把這個傳遞的move事件變成的cancel視頻講解:https://www.bilibili.com/video/BV1nY4y1e713/[1]

在這里插入圖片描述

那么疑問來了?這個又沒有存在systemserver傳遞事件時候就是已經(jīng)變成呢搞cancel了呢?如下圖:

在這里插入圖片描述

答案當(dāng)然是有的。下面就進行詳細(xì)分析

2、systemserver端變成cancel事件

復(fù)現(xiàn)場景: 1、手機設(shè)置成導(dǎo)航按鍵模式桌面點擊

在這里插入圖片描述

2 、點擊一個應(yīng)用進入,然后手指一直觸摸再應(yīng)用內(nèi) 3、然后另一個手點擊導(dǎo)航鍵home按鍵,讓會到桌面

以上3步即可以雜唉點擊進去的應(yīng)用內(nèi)接受到一個Cancel事件,因為手其實一直觸摸在屏幕,所以當(dāng)然不存在接受到up,但是畢竟這個時候應(yīng)用已經(jīng)被退到后臺,所以就只能給一個cancel事件給應(yīng)用。這個cancel事件就是systemserver中inputdispatcher傳遞給應(yīng)用的。

下面來進行源碼分析cancel事件在inputdispatcher產(chǎn)生

1、開啟日志 開放DEBUG_OUTBOUND_EVENT_DETAILS日志,這里可以用adb 命令也可以直接修改變成true

/**
?*?Log?detailed?debug?messages?about?each?outbound?event?processed?by?the?dispatcher.
?*?Enable?this?via?"adb?shell?setprop?log.tag.InputDispatcherOutboundEvent?DEBUG"?(requires?restart)
?*/

const?bool?DEBUG_OUTBOUND_EVENT_DETAILS?=
???????true;//?__android_log_is_loggable(ANDROID_LOG_DEBUG,?LOG_TAG?"OutboundEvent",?ANDROID_LOG_INFO);

2、復(fù)現(xiàn)時候查看日志

09-10?22:49:50.775??2231??2357?D?InputDispatcher:?channel?'a1b72df?com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity?(server)'?~?Synthesized?1?cancelation?events?to?bring?channel?back?in?sync?with?reality:?touched?window?was?removed,?mode=1.

這里即可以看出有同步一個cancel事件給com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity,大家注意這個原因是“touched window was removed”

可以根據(jù)這個reason來追一下相關(guān)代碼:

test@test:~/nx563j_xiaomi/frameworks/native$?grep?"touched?window?was?removed"?./?-rn
./services/inputflinger/dispatcher/InputDispatcher.cpp:4759:???????????????????????????????????????????????"touched?window?was?removed");

找到了在InputDispatcher的4759行:

/**
?*?Called?from?InputManagerService,?update?window?handle?list?by?displayId?that?can?receive?input.
?*?A?window?handle?contains?information?about?InputChannel,?Touch?Region,?Types,?Focused,...
?*?If?set?an?empty?list,?remove?all?handles?from?the?specific?display.
?*?For?focused?handle,?check?if?need?to?change?and?send?a?cancel?event?to?previous?one.
?*?For?removed?handle,?check?if?need?to?send?a?cancel?event?if?already?in?touch.
?*/

void?InputDispatcher::setInputWindowsLocked(
????????const?std::vector<sp<WindowInfoHandle>>&?windowInfoHandles,?int32_t?displayId)
?
{
???//省略部分
???//把inputdispatcher的window相關(guān)信息變成最新
???????updateWindowHandlesForDisplayLocked(windowInfoHandles,?displayId);

???//最為關(guān)鍵的mTouchStatesByDisplay變量,一般保存就是當(dāng)前觸摸事件的派發(fā)情況,主要保存了派發(fā)觸摸相關(guān)的window信息
????std::unordered_map<int32_t,?TouchState>::iterator?stateIt?=
????????????mTouchStatesByDisplay.find(displayId);
????if?(stateIt?!=?mTouchStatesByDisplay.end())?{
????????TouchState&?state?=?stateIt->second;
????????for?(size_t?i?=?0;?i?<?state.windows.size();)?{
????????????TouchedWindow&?touchedWindow?=?state.windows[i];
????????????//拿正在觸摸的window信息與最新的window的信息比較看看是否還存在,如果不在說明消失了
????????????if?(getWindowHandleLocked(touchedWindow.windowHandle)?==?nullptr)?{
??????????????
????????????????std::shared_ptr<InputChannel>?touchedInputChannel?=
????????????????????????getInputChannelLocked(touchedWindow.windowHandle->getToken());
????????????????if?(touchedInputChannel?!=?nullptr)?{
????????????????//開始觸發(fā)相關(guān)的cancel事件
????????????????????CancelationOptions?options(CancelationOptions::CANCEL_POINTER_EVENTS,
???????????????????????????????????????????????"touched?window?was?removed")
;
????????????????????synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel,?options);
???????????????
????????????????????}
????????????????}
????????????????state.windows.erase(state.windows.begin()?+?i);
????????????}?else?{
????????????????++i;
????????????}
????????}
//省略
}

setInputWindowsLocked主要是在系統(tǒng)有窗口window更新時候才會觸發(fā)調(diào)用,比如我們上面演示場景的,按home按鍵后應(yīng)用畫面要退出后臺,這個時候肯定應(yīng)用的window就沒有了,就會觸發(fā)改方法。 1、updateWindowHandlesForDisplayLocked 這里會把最新的window信息更新到inputdispatcher的mWindowHandlesByDisplay變量中 2、方法內(nèi)主要變量有一個mTouchStatesByDisplay:

最為關(guān)鍵的mTouchStatesByDisplay變量,一般保存就是當(dāng)前觸摸事件的派發(fā)情況,主要保存了派發(fā)觸摸相關(guān)的window信息

即代表當(dāng)前的觸摸事件派發(fā)相關(guān)window的的記錄

3、還有另一個關(guān)鍵方法getWindowHandleLocked

sp<WindowInfoHandle>?InputDispatcher::getWindowHandleLocked(
????????const?sp<IBinder>&?windowHandleToken)
?const?
{
????if?(windowHandleToken?==?nullptr)?{
????????return?nullptr;
????}
????????//就是拿傳入的windowHandleToken去mWindowHandlesByDisplay遍歷看看是否有
????for?(auto&?it?:?mWindowHandlesByDisplay)?{
????????const?std::vector<sp<WindowInfoHandle>>&?windowHandles?=?it.second;
????????for?(const?sp<WindowInfoHandle>&?windowHandle?:?windowHandles)?{
????????????if?(windowHandle->getToken()?==?windowHandleToken)?{
????????????????return?windowHandle;
????????????}
????????}
????}
????return?nullptr;
}

4、找到對應(yīng)刪除的window的inputchannel,傳遞對應(yīng)的cancel事件 //獲取touchedInputChannel ? ? ? std::shared_ptr touchedInputChannel = ? ? ? ? ? ? ? ? ? ? ? ?getInputChannelLocked(touchedWindow.windowHandle->getToken()); ? ? ? ? //派發(fā)cancel事件到touchedInputChannel ? ? ? ? ? ? ? ? ? ?synthesizeCancelationEventsForInputChannelLocked(touchedInputChannel, options);

如果發(fā)現(xiàn)更新之后的window的中已經(jīng)沒有了正在派發(fā)事件的window,那么說明window已經(jīng)被移除,然后就會觸發(fā)相關(guān)的cancel事件到原來的window。

最后更多干貨直接找千里馬可以+w ; androidframework007

引用鏈接

[1] 視頻講解:https://www.bilibili.com/video/BV1nY4y1e713/: https://www.bilibili.com/video/BV1nY4y1e713/


systemserver的inputdispatcher直接產(chǎn)生CANCEL事件原理分析-討厭的android觸摸面試題的評論 (共 條)

分享到微博請遵守國家法律
凉城县| 阿克| 息烽县| 海安县| 杂多县| 屯门区| 临沂市| 拉孜县| 通山县| 师宗县| 天等县| 千阳县| 阜阳市| 保山市| 万源市| 周口市| 苏尼特左旗| 易门县| 哈巴河县| 电白县| 宜兴市| 阳山县| 永兴县| 蓬莱市| 太白县| 南乐县| 鄂温| 永福县| 英超| 元朗区| 五莲县| 景洪市| 松桃| 浦东新区| 泸州市| 瑞丽市| 通渭县| 女性| 吉安市| 赤城县| 博客|