Android源码阅读技巧--查找开发者选项中显示触摸操作源码
<p> 在开发者模式下,在开发者选项中,可以勾选“显示触摸操作”,然后只要点击屏幕就会在点击的位置有圈圈显示。如何找到绘制圈圈的代码部分,有什么技巧来阅读代码量这么大的android系统源码呢?以下请跟着小老弟我来一起分析吧。</p><p> </p>
<p> 1. android设置功能的代码是在packages/apps/Settings/里面的,所以在Settings中搜寻关键的字符串,</p>
<p>在源码目录下终端输入</p>
<div class="cnblogs_code">
<pre>grep -rn <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">显示触摸操作</span><span style="color: rgba(128, 0, 0, 1)">"</span> ./packages/apps/Settings/</pre>
</div>
<p> 搜到如下:</p>
<div class="cnblogs_code">
<pre>./packages/apps/Settings/res/values-zh-rCN/strings.xml:<span style="color: rgba(128, 0, 128, 1)">2108</span>: <<span style="color: rgba(0, 0, 255, 1)">string</span> name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">show_touches</span><span style="color: rgba(128, 0, 0, 1)">"</span> msgid=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1356420386500834339</span><span style="color: rgba(128, 0, 0, 1)">"</span>><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">显示触摸操作</span><span style="color: rgba(128, 0, 0, 1)">"</span></<span style="color: rgba(0, 0, 255, 1)">string</span>></pre>
</div>
<p> 熟悉android应用编程的话就应该知道代码中 show_touches 与“显示触摸操作”是相关联的。</p>
<p><br> 2. 输入 </p>
<div class="cnblogs_code">
<pre>grep -rn <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">show_touches</span><span style="color: rgba(128, 0, 0, 1)">"</span> --include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*.java</span><span style="color: rgba(128, 0, 0, 1)">"</span> ./packages/apps/Settings/</pre>
</div>
<p> 得到</p>
<div class="cnblogs_code">
<pre>./packages/apps/Settings/src/com/android/settings/DevelopmentSettings.java:<span style="color: rgba(128, 0, 128, 1)">128</span>: <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> final String SHOW_TOUCHES_KEY = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">show_touches</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<p> </p>
<p> 3. 开始阅读源码,打开 DevelopmentSettings.java 按以下阅读顺序,</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> final String SHOW_TOUCHES_KEY = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">show_touches</span><span style="color: rgba(128, 0, 0, 1)">"</span>;</pre>
</div>
<div class="cnblogs_code">
<pre>mShowTouches = findAndInitSwitchPref(SHOW_TOUCHES_KEY);</pre>
</div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> writeShowTouchesOptions() {
Settings.System.putInt(getActivity().getContentResolver(),
Settings.System.SHOW_TOUCHES, mShowTouches.isChecked() </span>? <span style="color: rgba(128, 0, 128, 1)">1</span> : <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<p> 猜测 putInt 应该是一个数据传递的功能, 所以在framework里面搜 SHOW_TOUCHES 看看情况如何,</p>
<p> 输入</p>
<div class="cnblogs_code">
<pre>grep -rn <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SHOW_TOUCHES</span><span style="color: rgba(128, 0, 0, 1)">"</span> frameworks/</pre>
</div>
<p> 搜到好多,比如以下应该和数据处理注册相关,</p>
<div class="cnblogs_code">
<pre>frameworks/<span style="color: rgba(0, 0, 255, 1)">base</span>/core/java/android/provider/Settings.java:<span style="color: rgba(128, 0, 128, 1)">3094</span>: <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> final String SHOW_TOUCHES = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">show_touches</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
frameworks</span>/<span style="color: rgba(0, 0, 255, 1)">base</span>/core/java/android/provider/Settings.java:<span style="color: rgba(128, 0, 128, 1)">3097</span>: <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> final Validator SHOW_TOUCHES_VALIDATOR =<span style="color: rgba(0, 0, 0, 1)"> sBooleanValidator;
frameworks</span>/<span style="color: rgba(0, 0, 255, 1)">base</span>/core/java/android/provider/Settings.java:<span style="color: rgba(128, 0, 128, 1)">3439</span><span style="color: rgba(0, 0, 0, 1)">: PRIVATE_SETTINGS.add(SHOW_TOUCHES);
frameworks</span>/<span style="color: rgba(0, 0, 255, 1)">base</span>/core/java/android/provider/Settings.java:<span style="color: rgba(128, 0, 128, 1)">3519</span>: VALIDATORS.put(SHOW_TOUCHES, SHOW_TOUCHES_VALIDATOR);</pre>
</div>
<p> 因为看不出有什么特殊操作,只是一些声明和 add 操作,所以忽略之。。。。。。</p>
<p>以下才是具体功能</p>
<div class="cnblogs_code">
<pre>frameworks/<span style="color: rgba(0, 0, 255, 1)">base</span>/services/core/java/com/android/server/input/InputManagerService.java:<span style="color: rgba(128, 0, 128, 1)">1600</span>: Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), <span style="color: rgba(0, 0, 255, 1)">true</span>,</pre>
</div>
<p> </p>
<p> 4. 打开 InputManagerService.java 源码,</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> registerShowTouchesSettingObserver() {
mContext.getContentResolver().registerContentObserver(
Settings.System.getUriFor(Settings.System.SHOW_TOUCHES), </span><span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ContentObserver(mHandler) {
@Override
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onChange(boolean selfChange) {
updateShowTouchesFromSettings();
}
}, UserHandle.USER_ALL);
}</span></pre>
</div>
<p> 发现,关键方法 getContentResolver 刚好在DevelopmentSettings.java 中 putInt 里面的参数一致,所以可以肯定是走这里了。</p>
<p> 接下来跟方法 updateShowTouchesFromSettings()</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateShowTouchesFromSettings() {
</span><span style="color: rgba(0, 0, 255, 1)">int</span> setting = getShowTouchesSetting(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
nativeSetShowTouches(mPtr, setting </span>!= <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<p> 看到 native 字样,说明会走到用 cpp 写的 JNI 接口里面。</p>
<p> </p>
<p> 3. 因为已经到 JNI 了,所以后续都只需看 cpp 文件了,输入</p>
<div class="cnblogs_code">
<pre>grep -rn <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">nativeSetShowTouches</span><span style="color: rgba(128, 0, 0, 1)">"</span> --include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*.cpp</span><span style="color: rgba(128, 0, 0, 1)">"</span> ./frameworks/ </pre>
</div>
<p> 搜到</p>
<div class="cnblogs_code">
<pre>./frameworks/<span style="color: rgba(0, 0, 255, 1)">base</span>/services/core/jni/com_android_server_input_InputManagerService.cpp:<span style="color: rgba(128, 0, 128, 1)">1310</span>:<span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> nativeSetShowTouches(JNIEnv* <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> env </span><span style="color: rgba(0, 128, 0, 1)">*/</span>,</pre>
</div>
<p> 打开这份 com_android_server_input_InputManagerService.cpp 文件,</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> nativeSetShowTouches(JNIEnv* <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> env </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">,
jclass </span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> clazz </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)">, jlong ptr, jboolean enabled) {
NativeInputManager</span>* im = reinterpret_cast<NativeInputManager*><span style="color: rgba(0, 0, 0, 1)">(ptr);
im</span>-><span style="color: rgba(0, 0, 0, 1)">setShowTouches(enabled);
}</span></pre>
</div>
<p> 看看 setShowTouches 里面做了啥,</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">void</span> NativeInputManager::setShowTouches(<span style="color: rgba(0, 0, 255, 1)">bool</span><span style="color: rgba(0, 0, 0, 1)"> enabled) {
{ </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> acquire lock</span>
<span style="color: rgba(0, 0, 0, 1)"> AutoMutex _l(mLock);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (mLocked.showTouches ==<span style="color: rgba(0, 0, 0, 1)"> enabled) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
ALOGI(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Setting show touches feature to %s.</span><span style="color: rgba(128, 0, 0, 1)">"</span>, enabled ? <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">enabled</span><span style="color: rgba(128, 0, 0, 1)">"</span> : <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">disabled</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
mLocked.showTouches </span>=<span style="color: rgba(0, 0, 0, 1)"> enabled;
} </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> release lock</span>
<span style="color: rgba(0, 0, 0, 1)">
mInputManager</span>->getReader()-><span style="color: rgba(0, 0, 0, 1)">requestRefreshConfiguration(
InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
}</span></pre>
</div>
<p> 其中 mLocked.showTouches = enabled; 中 showTouches 是关键字,还有 CHANGE_SHOW_TOUCHES 也很关键。</p>
<p> </p>
<p> 4. 输入</p>
<div class="cnblogs_code">
<pre> grep -rn <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CHANGE_SHOW_TOUCHES</span><span style="color: rgba(128, 0, 0, 1)">"</span> --include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*.cpp</span><span style="color: rgba(128, 0, 0, 1)">"</span> ./frameworks/ </pre>
</div>
<p> 搜到</p>
<div class="cnblogs_code">
<pre>./frameworks/native/services/inputflinger/InputReader.cpp:<span style="color: rgba(128, 0, 128, 1)">3177</span>: | InputReaderConfiguration::CHANGE_SHOW_TOUCHES</pre>
</div>
<p> 打开 InputReader.cpp ,在 CHANGE_SHOW_TOUCHES 中看不出啥东西,太费力了。</p>
<p>这时可以在 InputReader.cpp 中搜 showTouches ,</p>
<p> 输入</p>
<div class="cnblogs_code">
<pre> grep -rn <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">showTouches</span><span style="color: rgba(128, 0, 0, 1)">"</span> --include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*.cpp</span><span style="color: rgba(128, 0, 0, 1)">"</span> ./frameworks/ </pre>
</div>
<p> 搜到</p>
<div class="cnblogs_code">
<pre>./frameworks/native/services/inputflinger/InputReader.cpp:<span style="color: rgba(128, 0, 128, 1)">3476</span>: (mDeviceMode == DEVICE_MODE_DIRECT &&<span style="color: rgba(0, 0, 0, 1)"> mConfig.showTouches)) {
.</span>/frameworks/native/services/inputflinger/InputReader.cpp:<span style="color: rgba(128, 0, 128, 1)">4334</span>: && mConfig.showTouches && mPointerController != NULL) {</pre>
</div>
<p> 如何把 CHANGE_SHOW_TOUCHES 与 showTouches 关联起来呢?在 InputReader.cpp 中,</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">if</span> (!changes || (changes &<span style="color: rgba(0, 0, 0, 1)"> (InputReaderConfiguration::CHANGE_DISPLAY_INFO
</span>|<span style="color: rgba(0, 0, 0, 1)"> InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT
</span>|<span style="color: rgba(0, 0, 0, 1)"> InputReaderConfiguration::CHANGE_SHOW_TOUCHES
</span>|<span style="color: rgba(0, 0, 0, 1)"> InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Configure device sources, surface dimensions, orientation and
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> scaling factors.</span>
configureSurface(when, &<span style="color: rgba(0, 0, 0, 1)">resetNeeded);
}</span></pre>
</div>
<p> </p>
<p> 进入configureSurface 发现以下关键代码</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Create pointer controller if needed.</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (mDeviceMode == DEVICE_MODE_POINTER ||<span style="color: rgba(0, 0, 0, 1)">
(mDeviceMode </span>== DEVICE_MODE_DIRECT &&<span style="color: rgba(0, 0, 0, 1)"> mConfig.showTouches)) {
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (mPointerController ==<span style="color: rgba(0, 0, 0, 1)"> NULL) {
mPointerController </span>= getPolicy()-><span style="color: rgba(0, 0, 0, 1)">obtainPointerController(getDeviceId());
}
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
mPointerController.clear();
}</span></pre>
</div>
<p> 这段注释耐人寻味 // Create pointer controller if needed.</p>
<p>所以可以肯定,后续就在 InputReader.cpp 里面围绕 showTouches 来搞事情,果然 showTouches 在另外一出显现它的重要,</p>
<div class="cnblogs_code">
<pre> <span style="color: rgba(0, 0, 255, 1)">if</span> (mDeviceMode ==<span style="color: rgba(0, 0, 0, 1)"> DEVICE_MODE_DIRECT
</span>&& mConfig.showTouches && mPointerController !=<span style="color: rgba(0, 0, 0, 1)"> NULL) {
mPointerController</span>-><span style="color: rgba(0, 0, 0, 1)">setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
mPointerController</span>-><span style="color: rgba(0, 0, 0, 1)">fade(PointerControllerInterface::TRANSITION_GRADUAL);
mPointerController</span>-><span style="color: rgba(0, 0, 0, 1)">setButtonState(mCurrentRawState.buttonState);
mPointerController</span>-><span style="color: rgba(0, 0, 0, 1)">setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex,
mCurrentCookedState.cookedPointerData.touchingIdBits);
}</span></pre>
</div>
<p> 学了多年的英语要发挥它的作用了,可知 setSpots 中 spots的中文意思为“斑点,小圆点”,所以就是走这里了,setSpots传的参数应该就和触摸坐标数据有关了。</p>
<p> </p>
<p> 5. 输入</p>
<div class="cnblogs_code">
<pre>grep -rn <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">setSpots</span><span style="color: rgba(128, 0, 0, 1)">"</span> --include <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*.cpp</span><span style="color: rgba(128, 0, 0, 1)">"</span> ./frameworks/</pre>
</div>
<p> 搜到</p>
<div class="cnblogs_code">
<pre>./frameworks/<span style="color: rgba(0, 0, 255, 1)">base</span>/libs/input/PointerController.cpp:<span style="color: rgba(128, 0, 128, 1)">246</span>:<span style="color: rgba(0, 0, 255, 1)">void</span> PointerController::setSpots(<span style="color: rgba(0, 0, 255, 1)">const</span> PointerCoords*<span style="color: rgba(0, 0, 0, 1)"> spotCoords,
.</span>/frameworks/<span style="color: rgba(0, 0, 255, 1)">base</span>/libs/input/PointerController.cpp:<span style="color: rgba(128, 0, 128, 1)">249</span>: ALOGD(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">setSpots: idBits=%08x</span><span style="color: rgba(128, 0, 0, 1)">"</span>, spotIdBits.value);</pre>
</div>
<p> 打开 PointerController.cpp ,在函数 void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex, BitSet32 spotIdBits)<br>中可知 spot->updateSprite(&icon, x, y); 与显示圈圈有关,大胆预测 icon 为显示的图形,x和y为显示的坐标。添加 ALOGI 打印,编译导入后发现,每次显示圈圈的时候,这里都会走。猜想变成真理!<br><br></p>
<p> 6. 思考,icon 数据来自哪里, 怎么就能在android上显示呢?x,y数据又是怎么传入的呢?以后有空再一起探讨吧。</p>
<p> </p><br><br>
来源:https://www.cnblogs.com/songsongman/p/11504744.html
頁:
[1]