开发者选项-显示点按操作反馈
开发者选项-显示点按操作反馈
Settings设置入口
首先查看界面中字串“显示点按操作反馈”:
在SettingsLib中,有字串show_touches
根据字串id查看对应的布局和代码调用
在Settings中,有对应的使用上述字串的布局文件res/xml/development_settings.xml
查看代码中操作控件后行为
显然在点击switch按钮后,会将0/1表示不启用/启用的状态写入到settings.system表中(show_touches)
框架监听获取
然后便是查看监听并获取该值的地方,查找代码在frameworks/base/services/core/java/com/android/server/input/InputManagerService.java中,有对Settings.System.SHOW_TOUCHES添加监听其
从上面截图代码可知,在InputManagerService启动的时候会对Settings.System.SHOW_TOUCHES添加监听(查看android14版本添加监听的地方有变更,这里以android12为例讲解,大致逻辑应该差别不大),在监听到变化时,会获取该值然后调用nativeSetShowTouches方法
nativeSetShowTouches
nativeSetShowTouches是个native方法查看其对应native方法(frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp)
从上面代码看到nativeSetShowTouches会调用NativeInputManager的setShowTouches方法,而setShowTouches方法主要做了两件事,一是将新的是否显示点按操作反馈的状态赋值给mLocked.showTouches,然后是调用了InputReader的requestRefreshConfiguration方法(这里mInputManager.getReader获取的就是inputflinger中的InputReader的对象)
在InputReader的requestRefreshConfiguration方法中主要也就将InputReaderConfiguration::CHANGE_SHOW_TOUCHES赋值给了mConfigurationChangesToRefresh
InputReader使用mConfigurationChangesToRefresh
在InputManagerService启动的时候会调用nativeStart方法,其会调用到inputflinger的InputManager的start方法,然后会调用InputReader的start方法如上,然后有创建InputThread,如上图在InputThread的构造方法中会创建InputThreadImpl并调用其run方法,InputThreadImpl继承Thread,所以创建InputThread后即会循环调用上面传入的loopOnce方法(这里分析了下inputflinger的部分启动逻辑,主要是因为其涉及InputReader相关调用与上面mConfigurationChangesToRefresh相关,所以简要介绍下逻辑)
这里回到InputReader中,在其loopOnce方法中
显然在InputReader中的loopOnce方法中,这里如果mConfigurationChangesToRefresh有变化,则会调用refreshConfigurationLocked方法
上面代码中与这里要讲的场景相关的逻辑主要就下面两行代码,
mPolicy->getReaderConfiguration(&mConfig);
device->configure(now, &mConfig, changes);
mPolicy->getReaderConfiguration(&mConfig)
这里mPolicy根据创建过程,即是NativeInputManager对象(com_android_server_input_InputManagerService.cpp)而其getReaderConfiguration方法,这里相关的主要是将前面开关的状态赋值给了InputReader的mConfig
device->configure(now, &mConfig, changes)
然后再看下device->configure(now, &mConfig, changes);的逻辑(InputDevice.cpp)
这里在这里的场景下主要会调用mapper.configure方法,这里mapper是InputMapper类型,根据这里的场景和手机一般的输入设备触屏,之类的mapper应该是TouchInputMapper类型,查看其configure方法
这里重新见到了前面change变化的项CHANGE_SHOW_TOUCHES,这里会调用configureSurface方法
在configureSurface中如果是打开显示点按操作反馈,则必然会对mPointerController赋值
而在touch事件时,会走到TouchInputMapper的cookAndDispatch方法,该方法中有调用updateTouchSpots
这里其实已经快到机器上看到的圆点了,这里对mPointerController的调用就是对圆点的相关设置
我们先看下这个mPointerController到底是什么
TouchInputMapper.cpp
InputReader.cpp
这里有看到mPolicy,前面分析过,是在native的cpp文件中
显然mPointerController就是PointerController的create方法创建的一个对象
而查看相关方法,如setSpots方法其又会调用到TouchSpotController::setSpots,然后会调用到SpriteController.cpp,在这里,终于看到了其显示相关的逻辑,在其doUpdateSprites方法中
在doUpdateSprites方法中有调用obtainSurface方法,而其看代码会调用到surfaceflinger接口去创建显示相关逻辑
在SpriteController的doUpdateSprites方法中还能看到如下代码
其中icon是SpriteIcon对象,其会绘制图片,这里图片是通过jni调到框架java层从framework-res系统资源中获取的(android_view_PointerIcon_getSystemIcon、android_view_PointerIcon_loadSystemIcon)
小节
分析到这里其实大部分逻辑都已经走读过了,剩下的一些细节暂不继续分析,其总体大致逻辑是设置打开开关后会通知到inputflinger,然后在分发事件时会刷新相关显示,不过整体涉及模块较多,包括设置应用,framework的java层,jni,inputflinger,libinputservice,还有系统资源等,所以相对比较复杂