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

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

安卓task/ActivityRecord縮放偏移后觸摸原理分析-Inputflinger/SurfaceFlinger源碼

2023-06-16 17:03 作者:千里馬學(xué)框架  | 我要投稿

hi,粉絲朋友們: 這兩天剛好在做自由窗口相關(guān)國(guó)內(nèi)需求,剛好遇到一個(gè)疑惑,那就是畫面進(jìn)行縮放后發(fā)現(xiàn)依然觸摸畫面可以正常反映問題。更多framework干貨知識(shí)手把手教學(xué)[1]

Log.i("千里馬qq群",“422901085”);

在這里插入圖片描述

具體疑惑背景

疑問點(diǎn)如下: 坐標(biāo)是針對(duì)屏幕的,按鈕也是相對(duì)Activity的,Activity本身寬度和屏幕一樣只是畫面被縮放了,Activity和View其實(shí)依然是屏幕的寬度,那么為啥屏幕坐標(biāo)點(diǎn)點(diǎn)擊到縮放Activity時(shí)候,按鈕依然可以正常相應(yīng)呢?

疑惑解答坐標(biāo)追蹤:

回憶坐標(biāo)傳遞流程: 觸摸事件坐標(biāo)肯定是 inputdispatcher ? -----> ?app

inputdispatcher坐標(biāo)確定

那么先確定inputDispatcher傳遞坐標(biāo),這個(gè)inputdispatcher的坐標(biāo)其實(shí)是可以通過dumpys來查看:

??RecentQueue:?length=10
????MotionEvent(deviceId=11,?eventTime=37449374871000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?909.9)]),?policyFlags=0x62000000,?age=1525ms
????MotionEvent(deviceId=11,?eventTime=37449382843000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?901.0)]),?policyFlags=0x62000000,?age=1517ms
????MotionEvent(deviceId=11,?eventTime=37449390835000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?898.9)]),?policyFlags=0x62000000,?age=1509ms
????MotionEvent(deviceId=11,?eventTime=37449470965000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?901.0)]),?policyFlags=0x62000000,?age=1429ms
????MotionEvent(deviceId=11,?eventTime=37449478951000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?903.0)]),?policyFlags=0x62000000,?age=1421ms
????MotionEvent(deviceId=11,?eventTime=37449486891000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?907.9)]),?policyFlags=0x62000000,?age=1413ms
????MotionEvent(deviceId=11,?eventTime=37449599726000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?904.9)]),?policyFlags=0x62000000,?age=1300ms
????MotionEvent(deviceId=11,?eventTime=37449607604000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?901.0)]),?policyFlags=0x62000000,?age=1292ms
????MotionEvent(deviceId=11,?eventTime=37449615411000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=MOVE,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?896.9)]),?policyFlags=0x62000000,?age=1284ms
????MotionEvent(deviceId=11,?eventTime=37449783797000,?source=TOUCHSCREEN?|?STYLUS,?displayId=0,?action=UP,?actionButton=0x00000000,?flags=0x00000000,?metaState=0x00000000,?buttonState=0x00000000,?classification=NONE,?edgeFlags=0x00000000,?xPrecision=22.8,?yPrecision=11.1,?xCursorPosition=nan,?yCursorPosition=nan,?pointers=[0:?(1011.9,?896.9)]),?policyFlags=0x62000000,?age=1116ms

明顯發(fā)現(xiàn)坐標(biāo)pointers=[0: (1011.9, 901.0)]), 這個(gè)屬于屏幕的絕對(duì)坐標(biāo),這個(gè)時(shí)候在inputdispatcher的傳遞時(shí)候并沒有被變化成和Activity的View一致坐標(biāo),即這里基本可以斷定inputdispatcher傳遞到app依然是屏幕的絕對(duì)坐標(biāo)。

app端坐標(biāo)確定

app端的坐標(biāo),這里一般可以通過debug調(diào)試方式,或之打印log的方式:

在這里插入圖片描述

這里在最初的的dispatchInputEvent進(jìn)行了斷點(diǎn),發(fā)現(xiàn)坐標(biāo)已經(jīng)變成了 1341,1633了

???private?void?dispatchInputEvent(int?seq,?InputEvent?event)?{
????????mSeqMap.put(event.getSequenceNumber(),?seq);
????????onInputEvent(event);
????}
即坐標(biāo)一旦到了java層面其實(shí)就已經(jīng)變成了和Activity正常的坐標(biāo)了,那么只能繼續(xù)往app層面地方往下追,這里就需要對(duì)native層面的input流程比較了解了,這里可以看馬哥課程的input專題有講解[2] ?鏈接參考https://ke.qq.com/course/package/83580?tuin=7d4eb354:

在這里插入圖片描述

那就來重點(diǎn)看看NativeInputEventReceiver::consumeEvents和InputConsumer.consume方法讀取相關(guān)input數(shù)據(jù)情況,最終發(fā)現(xiàn)MotionEvent是在void InputConsumer::initializeMotionEvent進(jìn)行構(gòu)造出來的:void?InputConsumer::initializeMotionEvent(MotionEvent*?event,?const?InputMessage*?msg)?{
????uint32_t?pointerCount?=?msg->body.motion.pointerCount;
????PointerProperties?pointerProperties[pointerCount];
????PointerCoords?pointerCoords[pointerCount];
????for?(uint32_t?i?=?0;?i?<?pointerCount;?i++)?{
????????pointerProperties[i].copyFrom(msg->body.motion.pointers[i].properties);
????????pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
????????ALOGE("initializeMotionEvent:?pointerCount?x=?%f?y?=?%f"?,pointerCoords[i].getX(),pointerCoords[i].getY());
????}
????????//這里是坐標(biāo)變化的關(guān)鍵轉(zhuǎn)換矩陣
????ui::Transform?transform;
????transform.set({msg->body.motion.dsdx,?msg->body.motion.dtdx,?msg->body.motion.tx,
???????????????????msg->body.motion.dtdy,?msg->body.motion.dsdy,?msg->body.motion.ty,?0,?0,?1});
????ui::Transform?displayTransform;
????displayTransform.set({msg->body.motion.dsdxRaw,?msg->body.motion.dtdxRaw,
??????????????????????????msg->body.motion.txRaw,?msg->body.motion.dtdyRaw,
??????????????????????????msg->body.motion.dsdyRaw,?msg->body.motion.tyRaw,?0,?0,?1});
????event->initialize(msg->body.motion.eventId,?msg->body.motion.deviceId,?msg->body.motion.source,
??????????????????????msg->body.motion.displayId,?msg->body.motion.hmac,?msg->body.motion.action,
??????????????????????msg->body.motion.actionButton,?msg->body.motion.flags,
??????????????????????msg->body.motion.edgeFlags,?msg->body.motion.metaState,
??????????????????????msg->body.motion.buttonState,?msg->body.motion.classification,?transform,
??????????????????????msg->body.motion.xPrecision,?msg->body.motion.yPrecision,
??????????????????????msg->body.motion.xCursorPosition,?msg->body.motion.yCursorPosition,
??????????????????????displayTransform,?msg->body.motion.downTime,?msg->body.motion.eventTime,
??????????????????????pointerCount,?pointerProperties,?pointerCoords);
????ALOGE("initializeMotionEvent:2??pointerCount?x=?%f?y?=?%f"?,event->getX(0),event->getY(0));
}

這里加入了相關(guān)的打印如下:

06-15?23:40:24.413??1850??1850?E?InputTransport:?initializeMotionEvent:?pointerCount?x=?1045.942383?y?=?930.961914
06-15?23:40:24.413??1850??1850?E?InputTransport:?initializeMotionEvent:2??pointerCount?x=?1371.884766?y?=?1693.923828

即可以看出,其實(shí)第一步從socket接受到的event坐標(biāo)依然是和inputdispatcher一樣,但是經(jīng)過event->initialize方法后,再打印時(shí)候就發(fā)現(xiàn)已經(jīng)變化了,變成和實(shí)際Activity一樣的相匹配的坐標(biāo)了。 其實(shí)本質(zhì)原因還是因?yàn)閕nitialize時(shí)候有傳遞相關(guān)的transform影響的,因?yàn)間etX方法時(shí)候?qū)嶋H會(huì)調(diào)用到對(duì)應(yīng)方法進(jìn)行坐標(biāo)轉(zhuǎn)換返回:

?/**
?????*?Get?the?X?coordinate?of?the?latest?sample?in?this?MotionEvent?for?pointer?'pointerIndex'.
?????*?Identical?to?calling?getHistoricalX(pointerIndex,?getHistorySize()).
?????*/

????inline?float?getX(size_t?pointerIndex)?const?{
????????return?getAxisValue(AMOTION_EVENT_AXIS_X,?pointerIndex);
????}
????float?MotionEvent::getAxisValue(int32_t?axis,?size_t?pointerIndex)?const?{
????return?getHistoricalAxisValue(axis,?pointerIndex,?getHistorySize());
}

float?MotionEvent::getHistoricalAxisValue(int32_t?axis,?size_t?pointerIndex,
??????????????????????????????????????????size_t?historicalIndex)
?const?
{
????const?PointerCoords&?coords?=?*getHistoricalRawPointerCoords(pointerIndex,?historicalIndex);
????//注意這個(gè)時(shí)候就是會(huì)有對(duì)應(yīng)的mTransform進(jìn)行影響,導(dǎo)致坐標(biāo)和屏幕坐標(biāo)產(chǎn)生差異
????return?calculateTransformedAxisValue(axis,?mSource,?mTransform,?coords);
}

上面清楚了,那剩下問題就是這個(gè)mTransform根源是來自哪里呢? 這里就又要回到inputdispatcher是有傳遞類似這種mTransform的。

???//?Publish?the?motion?event.
????????????????status?=?connection->inputPublisher
?????????????????????????????????.publishMotionEvent(dispatchEntry->seq,
?????????????????????????????????????????????????????dispatchEntry->resolvedEventId,
?????????????????????????????????????????????????????motionEntry.deviceId,?motionEntry.source,
?????????????????????????????????????????????????????motionEntry.displayId,?std::move(hmac),
?????????????????????????????????????????????????????dispatchEntry->resolvedAction,
?????????????????????????????????????????????????????motionEntry.actionButton,
?????????????????????????????????????????????????????dispatchEntry->resolvedFlags,
?????????????????????????????????????????????????????motionEntry.edgeFlags,?motionEntry.metaState,
?????????????????????????????????????????????????????motionEntry.buttonState,
?????????????????????????????????????????????????????motionEntry.classification,
?????????????????????????????????????????????????????dispatchEntry->transform,//這里就是關(guān)鍵的transform也會(huì)傳遞
?????????????????????????????????????????????????????motionEntry.xPrecision,?motionEntry.yPrecision,
?????????????????????????????????????????????????????motionEntry.xCursorPosition,
?????????????????????????????????????????????????????motionEntry.yCursorPosition,
?????????????????????????????????????????????????????dispatchEntry->rawTransform,
?????????????????????????????????????????????????????motionEntry.downTime,?motionEntry.eventTime,
?????????????????????????????????????????????????????motionEntry.pointerCount,
?????????????????????????????????????????????????????motionEntry.pointerProperties,?usingCoords);

這個(gè)transform其實(shí)dumpsys的input中也有展示:

??????5:?name='692067c?com.example.myapplication11/com.example.myapplication11.MainActivity',?id=163,?displayId=0,?inputConfig=0x0,?alpha=1.00,?frame=[360,84][1080,972],?globalScale=1.000000,?applicationInfo.name=ActivityRecord{f9088f2?u0?com.example.myapplication11/.MainActivity}?t465},?applicationInfo.token=0x7079fae2c370,?touchableRegion=[308,32][1133,1025],?ownerPid=1850,?ownerUid=10116,?dispatchingTimeout=5000ms,?hasToken=true,?touchOcclusionMode=BLOCK_UNTRUSTED
????????transform?(ROT_0)?(SCALE?TRANSLATE)
????????????2.0000??-0.0000??-720.0000
????????????-0.0000??2.0000??-168.0000
????????????0.0000??0.0000??1.0000

可以看到這個(gè)transform,大致矩陣即可以看出有放大2倍和偏移-720.0000,-168.0000,也正是這個(gè)轉(zhuǎn)換才導(dǎo)致的由屏幕的絕對(duì)坐標(biāo)轉(zhuǎn)換到Activity的絕對(duì)坐標(biāo),轉(zhuǎn)換后Activity可以獲取到正常的坐標(biāo)進(jìn)行響應(yīng)。

那么問題又來了請(qǐng)問inputdispatcher這個(gè)transform的轉(zhuǎn)換又來自哪里呢?

哈哈這里就又回到之前input的專題講解的,這個(gè)windowinfo信息實(shí)際是來自于SurfaceFlinger的,這里來看看dumpsys SurfaceFlinger是否又相關(guān)信息:

*?Layer?0x71a7e2b523f0?(com.example.myapplication11/com.example.myapplication11.MainActivity#268)
??????isSecure=false?geomUsesSourceCrop=true?geomBufferUsesDisplayInverseTransform=false?geomLayerTransform?(ROT_0)?(SCALE?TRANSLATE)
????0.5000??0.0000??360.0000
????0.0000??0.5000??84.0000
????0.0000??0.0000??1.0000

找到對(duì)應(yīng)的window Layer確實(shí)看到了一個(gè)矩陣,但是好像這個(gè)矩陣和input的矩陣不一樣,但是好像有點(diǎn)關(guān)系,這個(gè)關(guān)系是啥呢?哈哈就是一個(gè)類是逆向過程,相當(dāng)于surface顯示時(shí)候縮小到原來0.5,那么回去時(shí)候就需要放大2倍才可以還原。而surfaceflinger這個(gè)矩陣就是進(jìn)行surfacecontrol進(jìn)行操作的縮放矩陣。

故到此整個(gè)環(huán)節(jié)就已經(jīng)清楚了,總結(jié)一下如下圖:

在這里插入圖片描述

引用鏈接

[1] 更多framework干貨知識(shí)手把手教學(xué): https://ke.qq.com/course/package/83580
[2] 馬哥課程的input專題有講解: https://ke.qq.com/course/package/83580?tuin=7d4eb354


安卓task/ActivityRecord縮放偏移后觸摸原理分析-Inputflinger/SurfaceFlinger源碼的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
平乐县| 铜山县| 云林县| 龙岩市| 缙云县| 肇源县| 澎湖县| 奉节县| 寿宁县| 留坝县| 宣恩县| 永春县| 五台县| 广州市| 永康市| 徐水县| 通化县| 徐汇区| 图片| 伊通| 凉城县| 额济纳旗| 泰顺县| 朝阳区| 宁城县| 成安县| 恭城| 镇巴县| 白沙| 宣武区| 阿荣旗| 长宁区| 灌云县| 通江县| 兖州市| 左云县| 托克逊县| 赤壁市| 东港市| 原阳县| 玛沁县|