開發者選項-顯示點按操作反饋
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,還有系統資源等,所以相對比較複雜