Android 开发者指针位置调试问题
问题现象
系统开发者选项中,开启指针位置调试后发现一些界面按钮等点击无反应。
代码分析
通过代码看:开启指针位置调试是修改 Settings.System.POINTER_LOCATION 属性值。而系统 WMS 中通过 SettingsObserver 内部类监听此属性值变化,执行 updatePointerLocation() 函数,最后在 DisplayPolicy::enablePointerLocation() 方法中创建 PointerLocationView 添加到系统窗口中。t同时对系统Input事件加入监听等。
而系统 View 的 dispatchTouchEvent 方法中,有一个 onFilterTouchEventForSecurity 判断条件
/**
* Pass the touch screen motion event down to the target view, or this
* view if it is the target.
*
* @param event The motion event to be dispatched.
* @return True if the event was handled by the view, false otherwise.
*/
public boolean dispatchTouchEvent(MotionEvent event) {
// If the event should be handled by accessibility focus first.
... ...
final int actionMasked = event.getActionMasked();
if (actionMasked == MotionEvent.ACTION_DOWN) {
// Defensive cleanup for new gesture
stopNestedScroll();
}
if (onFilterTouchEventForSecurity(event)) {
if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
result = true;
}
//noinspection SimplifiableIfStatement
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnTouchListener != null
&& (mViewFlags & ENABLED_MASK) == ENABLED
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
}
... ...
return result;
}
... ...
public boolean onFilterTouchEventForSecurity(MotionEvent event) {
//noinspection RedundantIfStatement
if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
&& (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
// Window is obscured, drop this touch.
return false;
}
return true;
}
结论
从指针位置的 PointerLocationView 分下来的 MotionEvent 都被设置 MotionEvent.FLAG_WINDOW_IS_OBSCURED 的标签,所以一些 View 如果设置 FILTER_TOUCHES_WHEN_OBSCURED 属性值,就出现开启指针位置后,点击、滑动等 input 事件被拦截的情形。
FILTER_TOUCHES_WHEN_OBSCURED 属性值除了代码中设置之外,也可以通过 AndroidManifest.xml 中 android:theme 指定配置,对应配置子项如下:
<style name="Settings.FilterTouches">
<item name="android:filterTouchesWhenObscured">false</item>
</style>