背景:
学员粉丝朋友们在学习马哥的android framework实战高级课程时候,有一些细心的学员提出了一个无问题,那就是再看dumpsys SurfaceFlinger的图层或者是dumpsys input相关信息时候发现了一个叫做ActivityRecordInputSink的图层。
如下图所示:
dumpsys input可以看到一个ActivityRecordInputSink在Activity的下面
再看看sf的相关:
以上都看到了一个ActivityRecordInputSink的图层,那么这个图层到底有啥作用呢?其实网络上基本上也没有资料,我这边blog算是一个开疆扩土的探索。。。
线索寻找1:
找到这个类看看有没有相关注释:
个人翻译理解:
* Creates a InputWindowHandle that catches all touches that would otherwise pass through an* Activity.
字面翻译就是ActivityRecordInputSink会捕获所有本身会穿透Activity的触摸,即ActivityRecordInputSink就相当于一张大网,Activity有点相当于大网上面有一张小网。
即正常情况下Activity这个小网和手机屏幕都是一样大小,所以这个时候其实ActivityRecordInputSink就没啥存在感,因为本身Activity的任何事件都会捕获,根本不会有漏网之鱼事件到ActivityRecordInputSink。
上图展示的Activity大小和手机屏幕大小一样,所以手机触摸事件根本到达不了ActivityRecordInputSink这个地方。
其实这个也就是ActivityRecordInputSink为啥没引起大家重视原因,因为我们大部分情况下都遇不到它。
可以看看正常情况下两者的dumpsys input的touch区域:
5: name='8bdb43d com.android.messaging/com.android.messaging.ui.conversationlist.ConversationListActivity', id=567, displayId=0, inputConfig=0x0, alpha=1.00, frame=[0,0][1080,2160], globalScale=1.000000, applicationInfo.name=ActivityRecord{4e0ab6e u0 com.android.messaging/.ui.conversationlist.ConversationListActivity} t201}, applicationInfo.token=0x792c4556f0, touchableRegion=[0,0][1080,2160], ownerPid=3580, ownerUid=10127, dispatchingTimeout=5000ms, hasToken=true, touchOcclusionMode=BLOCK_UNTRUSTEDtransform (ROT_0) (IDENTITY)6: name='a06edb3 ActivityRecordInputSink com.android.messaging/.ui.conversationlist.ConversationListActivity', id=210, displayId=0, inputConfig=NO_INPUT_CHANNEL | NOT_FOCUSABLE, alpha=1.00, frame=[0,0][0,0], globalScale=0.000000, applicationInfo.name=, applicationInfo.token=<null>, touchableRegion=[-10799,-21599][10800,21600], ownerPid=1887, ownerUid=1000, dispatchingTimeout=0ms, hasToken=false, touchOcclusionMode=BLOCK_UNTRUSTEDtransform (ROT_0) (IDENTITY)
可以看到Activity的窗口显示大小就是touchableRegion=[0,0][1080,2160]即和屏幕大小一样,而ActivityRecordInputSink大小是touchableRegion=[-10799,-21599][10800,21600]明显比手机屏幕大很多,这种Activity大小和手机手机屏幕一样,触摸事件正常都不可能到这里。
线索寻找2
那么什么情况下下这个ActivityRecordInputSink才会有相关的作用的呢?
继续寻找一下ActivityRecordInputSink这个类提交log线索:
git log提交
commit 1bc541e8950824f223dc2aba43f09c20f96189a9
Author: Linus Tufvesson <lus@google.com>
Date: Wed Nov 3 13:56:24 2021 +0000Block touches from passing through activitiesBy setting an InputWindowHandle for ActivityRecord it is no longerpossible for Activities to shrink their own window size to allow touchesto pass through to activities behind. The touchable region is cropped bythe parent, meaning that it will occupy all availble space.Feature is disabled by default and can be enabled per package using adbshell am compat enable ENABLE_TOUCH_OPAQUE_ACTIVITIES <package>Test: Manually enabled appcompat feature and verified with sample fromb/194480991 that touches are blocked.
核心语句翻译:
By setting an InputWindowHandle for ActivityRecord it is no longer
possible for Activities to shrink their own window size to allow touches
to pass through to activities behind. The touchable region is cropped by
the parent, meaning that it will occupy all availble space.
即一旦有了ActivityRecordInputSink后就没有可能出现Activity自己窗口缩小允许触摸事件传递到Activity底部的窗口情况,所有的触摸都会被ActivityRecordInputSink获取。
如上图activity可能比屏幕小,但是触摸在activity外的触摸不会被传递给底部的window,因为会被ActivityRecordInputSink收走。
通过实际dumpsys来验证看看是否真的是这么一回事?
5: name='4d95871 com.example.myapplication11/com.example.myapplication11.MainActivity', id=1974, displayId=0, inputConfig=0x0, alpha=1.00, frame=[0,0][864,1536], globalScale=1.000000, applicationInfo.name=ActivityRecord{596e7da u0 com.example.myapplication11/.MainActivity} t51}, applicationInfo.token=0x6f95368f10, touchableRegion=[0,0][864,1536], ownerPid=12666, ownerUid=10138, dispatchingTimeout=5000ms, hasToken=true, touchOcclusionMode=BLOCK_UNTRUSTEDtransform (ROT_0) (SCALE )1.2500 -0.0000 0.0000-0.0000 1.2500 0.00000.0000 0.0000 1.00006: name='1b027ef ActivityRecordInputSink com.example.myapplication11/.MainActivity', id=1979, displayId=0, inputConfig=NO_INPUT_CHANNEL | NOT_FOCUSABLE, alpha=1.00, frame=[0,0][0,0], globalScale=0.000000, applicationInfo.name=, applicationInfo.token=<null>, touchableRegion=[-10799,-19199][10800,19200], ownerPid=9926, ownerUid=1000, dispatchingTimeout=0ms, hasToken=false, touchOcclusionMode=BLOCK_UNTRUSTEDtransform (ROT_0) (IDENTITY)7: name='9fe7939 com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher', id=1952, displayId=0, inputConfig=DUPLICATE_TOUCH_TO_WALLPAPER, alpha=1.00, frame=[0,0][1080,1920], globalScale=1.000000, applicationInfo.name=ActivityRecord{228f121 u0 com.android.launcher3/.uioverrides.QuickstepLauncher} t45}, applicationInfo.token=0x6f95359f70, touchableRegion=[0,0][1080,1920], ownerPid=10363, ownerUid=10111, dispatchingTimeout=5000ms, hasToken=true, touchOcclusionMode=BLOCK_UNTRUSTEDtransform (ROT_0) (IDENTITY)8: name='ada6de9 ActivityRecordInputSink com.android.launcher3/.uioverrides.QuickstepLauncher', id=1851, displayId=0, inputConfig=NO_INPUT_CHANNEL | NOT_FOCUSABLE, alpha=1.00, frame=[0,0][0,0], globalScale=0.000000, applicationInfo.name=, applicationInfo.token=<null>, touchableRegion=[-10799,-19199][10800,19200], ownerPid=9926, ownerUid=1000, dispatchingTimeout=0ms, hasToken=false, touchOcclusionMode=BLOCK_UNTRUSTEDtransform (ROT_0) (IDENTITY)
上面可以看到4d95871 com.example.myapplication11/com.example.myapplication11.MainActivity 这个Activity触摸大小区域:
touchableRegion=[0,0][864,1536]
屏幕大小是1080x1920
但是底下的ActivityRecordInputSink的大小如下
ActivityRecordInputSink com.example.myapplication11/.MainActivity
touchableRegion=[-10799,-19199][10800,19200],
所以有ActivityRecordInputSink在触摸事件不会传递给下面的Launcher
本文章更多详细代码和资料需要购买课程获取
七件套专题:
点击这里
https://mp.weixin.qq.com/s/Qv8zjgQ0CkalKmvi8tMGaw
hal+perfetto+surfaceflinger
https://mp.weixin.qq.com/s/LbVLnu1udqExHVKxd74ILg
私聊作者+v(androidframework007)
视频试看:
https://www.bilibili.com/video/BV1wc41117L4/