经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Android源码阅读技巧--查找开发者选项中显示触摸操作源码
来源:cnblogs  作者:啊源股  时间:2019/9/12 8:56:01  对本文有异议

    在开发者模式下,在开发者选项中,可以勾选“显示触摸操作”,然后只要点击屏幕就会在点击的位置有圈圈显示。如何找到绘制圈圈的代码部分,有什么技巧来阅读代码量这么大的android系统源码呢?以下请跟着小老弟我来一起分析吧。

 

    1. android设置功能的代码是在packages/apps/Settings/里面的,所以在Settings中搜寻关键的字符串,

在源码目录下终端输入

  1. grep -rn "显示触摸操作" ./packages/apps/Settings/

    搜到如下:

  1. ./packages/apps/Settings/res/values-zh-rCN/strings.xml:2108: <string name="show_touches" msgid="1356420386500834339">"显示触摸操作"</string>

    熟悉android应用编程的话就应该知道代码中 show_touches 与“显示触摸操作”是相关联的。


    2. 输入 

  1. grep -rn "show_touches" --include "*.java" ./packages/apps/Settings/

    得到

  1. ./packages/apps/Settings/src/com/android/settings/DevelopmentSettings.java:128: private static final String SHOW_TOUCHES_KEY = "show_touches";

 

    3. 开始阅读源码,打开 DevelopmentSettings.java 按以下阅读顺序,

  1. private static final String SHOW_TOUCHES_KEY = "show_touches";
  1. mShowTouches = findAndInitSwitchPref(SHOW_TOUCHES_KEY);
  1. private void writeShowTouchesOptions() {
  2. Settings.System.putInt(getActivity().getContentResolver(),
  3. Settings.System.SHOW_TOUCHES, mShowTouches.isChecked() ? 1 : 0);
  4. }

    猜测 putInt 应该是一个数据传递的功能, 所以在framework里面搜 SHOW_TOUCHES 看看情况如何,

    输入

  1. grep -rn "SHOW_TOUCHES" frameworks/

    搜到好多,比如以下应该和数据处理注册相关,

  1. frameworks/base/core/java/android/provider/Settings.java:3094: public static final String SHOW_TOUCHES = "show_touches";
  2. frameworks/base/core/java/android/provider/Settings.java:3097: public static final Validator SHOW_TOUCHES_VALIDATOR = sBooleanValidator;
  3. frameworks/base/core/java/android/provider/Settings.java:3439: PRIVATE_SETTINGS.add(SHOW_TOUCHES);
  4. frameworks/base/core/java/android/provider/Settings.java:3519: VALIDATORS.put(SHOW_TOUCHES, SHOW_TOUCHES_VALIDATOR);

    因为看不出有什么特殊操作,只是一些声明和 add 操作,所以忽略之。。。。。。

以下才是具体功能

  1. frameworks/base/services/core/java/com/android/server/input/InputManagerService.java:1600: Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,

 

    4. 打开 InputManagerService.java 源码,

  1. private void registerShowTouchesSettingObserver() {
  2. mContext.getContentResolver().registerContentObserver(
  3. Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), true,
  4. new ContentObserver(mHandler) {
  5. @Override
  6. public void onChange(boolean selfChange) {
  7. updateShowTouchesFromSettings();
  8. }
  9. }, UserHandle.USER_ALL);
  10. }

    发现,关键方法 getContentResolver 刚好在DevelopmentSettings.java 中 putInt 里面的参数一致,所以可以肯定是走这里了。

    接下来跟方法 updateShowTouchesFromSettings()

  1. public void updateShowTouchesFromSettings() {
  2. int setting = getShowTouchesSetting(0);
  3. nativeSetShowTouches(mPtr, setting != 0);
  4. }

    看到 native 字样,说明会走到用 cpp 写的 JNI 接口里面。

 

    3. 因为已经到 JNI 了,所以后续都只需看 cpp 文件了,输入

  1. grep -rn "nativeSetShowTouches" --include "*.cpp" ./frameworks/

    搜到

  1. ./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp:1310:static void nativeSetShowTouches(JNIEnv* /* env */,

   打开这份 com_android_server_input_InputManagerService.cpp 文件,

  1. static void nativeSetShowTouches(JNIEnv* /* env */,
  2. jclass /* clazz */, jlong ptr, jboolean enabled) {
  3. NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
  4. im->setShowTouches(enabled);
  5. }

    看看 setShowTouches 里面做了啥,

  1. void NativeInputManager::setShowTouches(bool enabled) {
  2. { // acquire lock
  3. AutoMutex _l(mLock);
  4. if (mLocked.showTouches == enabled) {
  5. return;
  6. }
  7. ALOGI("Setting show touches feature to %s.", enabled ? "enabled" : "disabled");
  8. mLocked.showTouches = enabled;
  9. } // release lock
  10. mInputManager->getReader()->requestRefreshConfiguration(
  11. InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
  12. }

    其中 mLocked.showTouches = enabled; 中 showTouches 是关键字,还有 CHANGE_SHOW_TOUCHES 也很关键。

 

    4. 输入

  1. grep -rn "CHANGE_SHOW_TOUCHES" --include "*.cpp" ./frameworks/

    搜到

  1. ./frameworks/native/services/inputflinger/InputReader.cpp:3177: | InputReaderConfiguration::CHANGE_SHOW_TOUCHES

    打开 InputReader.cpp ,在 CHANGE_SHOW_TOUCHES 中看不出啥东西,太费力了。

这时可以在 InputReader.cpp 中搜 showTouches ,

    输入

  1. grep -rn "showTouches" --include "*.cpp" ./frameworks/

    搜到

  1. ./frameworks/native/services/inputflinger/InputReader.cpp:3476: (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
  2. ./frameworks/native/services/inputflinger/InputReader.cpp:4334: && mConfig.showTouches && mPointerController != NULL) {

    如何把 CHANGE_SHOW_TOUCHES 与 showTouches 关联起来呢?在 InputReader.cpp 中,

  1. if (!changes || (changes & (InputReaderConfiguration::CHANGE_DISPLAY_INFO
  2. | InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
  3. | InputReaderConfiguration::CHANGE_SHOW_TOUCHES
  4. | InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
  5. // Configure device sources, surface dimensions, orientation and
  6. // scaling factors.
  7. configureSurface(when, &resetNeeded);
  8. }

 

    进入configureSurface 发现以下关键代码

  1. // Create pointer controller if needed.
  2. if (mDeviceMode == DEVICE_MODE_POINTER ||
  3. (mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
  4. if (mPointerController == NULL) {
  5. mPointerController = getPolicy()->obtainPointerController(getDeviceId());
  6. }
  7. } else {
  8. mPointerController.clear();
  9. }

    这段注释耐人寻味 // Create pointer controller if needed.

所以可以肯定,后续就在 InputReader.cpp 里面围绕 showTouches 来搞事情,果然 showTouches 在另外一出显现它的重要,

  1. if (mDeviceMode == DEVICE_MODE_DIRECT
  2. && mConfig.showTouches && mPointerController != NULL) {
  3. mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
  4. mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
  5. mPointerController->setButtonState(mCurrentRawState.buttonState);
  6. mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
  7. mCurrentCookedState.cookedPointerData.idToIndex,
  8. mCurrentCookedState.cookedPointerData.touchingIdBits);
  9. }

    学了多年的英语要发挥它的作用了,可知 setSpots 中 spots的中文意思为“斑点,小圆点”,所以就是走这里了,setSpots传的参数应该就和触摸坐标数据有关了。

 

    5. 输入

  1. grep -rn "setSpots" --include "*.cpp" ./frameworks/

    搜到

  1. ./frameworks/base/libs/input/PointerController.cpp:246:void PointerController::setSpots(const PointerCoords* spotCoords,
  2. ./frameworks/base/libs/input/PointerController.cpp:249: ALOGD("setSpots: idBits=%08x", spotIdBits.value);

    打开 PointerController.cpp ,在函数 void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, BitSet32 spotIdBits)
中可知 spot->updateSprite(&icon, x, y); 与显示圈圈有关,大胆预测 icon 为显示的图形,x和y为显示的坐标。添加 ALOGI 打印,编译导入后发现,每次显示圈圈的时候,这里都会走。猜想变成真理!

    6. 思考,icon 数据来自哪里, 怎么就能在android上显示呢?x,y数据又是怎么传入的呢?以后有空再一起探讨吧。

 

原文链接:http://www.cnblogs.com/songsongman/p/11504744.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号