Android4.2移植的debug之路——不明黑色光圈

    Android 4.2的移植工作仍然进行中,目前遇到一个bug:在qemu上,android界面出来后,用鼠标点击屏幕时会有一个黑色的小光圈,这个光圈不会跟着鼠标移动,只有点击后再拖动它才会跟着动,如果我想启动某个应用程序,需要把该光圈拖到应用程序图标位置上,然后双击才能启动。上图:


    一个让人措手不及的bug,从未见过,又找不到相关的资料,只能“始作俑者”了。这是驱动问题?还是android上层问题?都有可能!首先去查看logcat的输出信息,寻找是否有可疑的地方。最后看到这里比较像问题发生之处:

I/SystemServer(  723): Input Method Service
I/EventHub(  723): New device: id=1, fd=80, path='/dev/input/event0', name='ic1-keypad', classes=0x1, configuration='', keyLayout='/system/usr/keylayout/Generic.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm', builtinKeyboard=true, usingSuspendBlockIoctl=true, usingClockIoctl=true
D/EventHub(  723): No input device configuration file found for device 'ic1_dano_ts'.
I/EventHub(  723): New device: id=2, fd=82, path='/dev/input/event1', name='ic1_dano_ts', classes=0x4, configuration='', keyLayout='', keyCharacterMap='', builtinKeyboard=false, usingSuspendBlockIoctl=true, usingClockIoctl=true
W/InputMethodManagerService(  723): Couldn't create dir.: /data/system/inputmethod
I/InputReader(  723): Device added: id=-1, name='Virtual', sources=0x00000301
I/InputReader(  723):   Touch device 'ic1_dano_ts' could not query the properties of its associated display.  The device will be inoperable until the display size becomes available.
I/InputReader(  723): Device added: id=2, name='ic1_dano_ts', sources=0x00002002
I/InputReader(  723): Device added: id=0, name='ic1-keypad', sources=0x00000101
W/InputMethodManagerService(  723): No IME selected. Choose the most applicable IME.
I/ActivityManager(  723): Config changed: {1.0 ?mcc?mnc en_US ldltr sw272dp w438dp h247dp 160dpi smll land ?uimode ?night -touch -keyb/h/h -nav/h s.2}
I/InputReader(  723): Reconfiguring input devices.  changes=0x00000004
I/InputReader(  723): Device reconfigured: id=2, name='ic1_dano_ts', size 480x272, orientation 0, mode 3, display id 0

上面的log显示,EventHub发现了两个设备节点/dev/input/event0和/dev/input/event1,分别对应按键输入和触摸屏输入,但是这一句:

I/InputReader(  723):   Touch device 'ic1_dano_ts' could not query the properties of its associated display.  The device will be inoperable until the display size becomes available.

看起来像是触摸屏的参数没有设置好。所以当android上层的InputReader要去查询触摸屏设备的参数时就失败了,然后InputReader自己采用了默认的方法来设置触摸屏的参数:

I/InputReader(  723): Device reconfigured: id=2, name='ic1_dano_ts', size 480x272, orientation 0, mode 3, display id 0

    所以,我怀疑qemu中触摸屏的分辨率没有设置好,在驱动里面把它设置成480x272,可是问题还是没解决。回头去观察这个光圈的特点,感觉它好像把输入事件跟android的界面隔开了,输入事件全都被光圈接收,传不到光圈下面的android界面。那好,我就瞧瞧你这光圈是一个什么对象。android里面默认是把很多debug信息屏蔽的,我们可以手动把它们打开。既然想要知道光圈是什么对象,那么就要看究竟是谁接收了输入事件。所以把ActivityManagerService和WindowManagerService里面的debug信息打开,它们可以看到每个activity或者窗口的动作。如何打开debug信息?这里举例WindowManagerService,其它的对象方法相同。在WindowManagerService中把下面这些debug的宏赋值为true就行了。

 static final String TAG = "WindowManager";
  176     static final boolean DEBUG = false;
  177     static final boolean DEBUG_ADD_REMOVE = false;
  178     static final boolean DEBUG_FOCUS = false;
  179     static final boolean DEBUG_ANIM = false;
  180     static final boolean DEBUG_LAYOUT = false;
  181     static final boolean DEBUG_RESIZE = false;
  182     static final boolean DEBUG_LAYERS = false;
  183     static final boolean DEBUG_INPUT = false;
  184     static final boolean DEBUG_INPUT_METHOD = false;
  185     static final boolean DEBUG_VISIBILITY = false;
  186     static final boolean DEBUG_WINDOW_MOVEMENT = false;
  187     static final boolean DEBUG_TOKEN_MOVEMENT = false;
  188     static final boolean DEBUG_ORIENTATION = false;
  189     static final boolean DEBUG_APP_ORIENTATION = false;
  190     static final boolean DEBUG_CONFIGURATION = false;
  191     static final boolean DEBUG_APP_TRANSITIONS = false;
  192     static final boolean DEBUG_STARTING_WINDOW = false;
  193     static final boolean DEBUG_REORDER = false;
  194     static final boolean DEBUG_WALLPAPER = false;
  195     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
  196     static final boolean DEBUG_DRAG = false;
  197     static final boolean DEBUG_SCREEN_ON = false;
  198     static final boolean DEBUG_SCREENSHOT = false;
  199     static final boolean DEBUG_BOOT = false;
  200     static final boolean DEBUG_LAYOUT_REPEATS = true;
  201     static final boolean DEBUG_SURFACE_TRACE = false;
  202     static final boolean DEBUG_WINDOW_TRACE = false;

    把debug信息打开后,用鼠标点击android界面时,竟然没有activty和window的动作信息输出,嚓,这是要闹那样!!看来想知道光圈是什么对象是不可能了,此路不通走别的。还有什么方法可以调试?既然事件接受的路径调试不了,还有事件的分发可以调试。在android中,InputDispatcher就是事件的分发器。把事件分发这条路径的debug信息打开,点击qemu界面时,有log输出,证明android是能收到点击事件。具体的log我没保存好,弄丢了,然后又不想重做镜像重启androd,所以这里就不把事件分发的log贴上来了。只有这些log也不能解决问题,有对比才有发现。所以我编了一个mips的镜像,在goldfish上启动,也把事件分发的debug信息打开,发现输出的log确实不一样。goldfish上输出的log是这样的:

D/InputReader(  277): BatchSize: 4 Count: 4
D/InputReader(  277): Input event: device=0 type=0x0003 code=0x0000 value=0x0000006d when=716025815000
D/InputReader(  277): Input event: device=0 type=0x0003 code=0x0001 value=0x00000149 when=716025843000
D/InputReader(  277): Input event: device=0 type=0x0001 code=0x014a value=0x00000001 when=716025863000
D/InputReader(  277): Input event: device=0 type=0x0000 code=0x0000 value=0x00000000 when=716025873000
D/InputReader(  277): syncTouch: pointerCount 0 -> 1, touching ids 0x00000000 -> 0x80000000, hovering ids 0x00000000 -> 0x00000000
D/InputDispatcher(  277): notifyMotion - eventTime=716025873000, deviceId=0, source=0x1002, policyFlags=0x0, action=0x0, flags=0x0, metaState=0x0, buttonState=0x0, edgeFlags=0x0, xPrecision=1.000000, yPrecision=1.000000, downTime=716025873000
D/InputDispatcher(  277):   Pointer 0: id=0, toolType=1, x=109.000000, y=329.000000, pressure=1.000000, size=0.000000, touchMajor=0.000000, touchMinor=0.000000, toolMajor=0.000000, toolMinor=0.000000, orientation=0.000000
D/InputDispatcher(  277): Resetting ANR timeouts.
D/InputDispatcher(  277): dispatchMotion - eventTime=716025873000, deviceId=0, source=0x1002, policyFlags=0x62000000, action=0x0, flags=0x0, metaState=0x0, buttonState=0x0, edgeFlags=0x0, xPrecision=1.000000, yPrecision=1.000000, downTime=716025873000
D/InputDispatcher(  277):   Pointer 0: id=0, toolType=1, x=109.000000, y=329.000000, pressure=1.000000, size=0.000000, touchMajor=0.000000, touchMinor=0.000000, toolMajor=0.000000, toolMinor=0.000000, orientation=0.000000
D/InputDispatcher(  277): findTouchedWindow finished: injectionResult=0, injectionPermission=1, timeSpentWaitingForApplication=0.0ms
D/InputDispatcher(  277): dispatchEventToCurrentInputTargets
D/InputDispatcher(  277): channel '2c3a5020 com.android.launcher/com.android.launcher2.Launcher (server)' ~ prepareDispatchCycle - flags=0x00000105, xOffset=0.000000, yOffset=0.000000, scaleFactor=1.000000, pointerIds=0x80000000
D/InputDispatcher(  277): channel '2c3a5020 com.android.launcher/com.android.launcher2.Launcher (server)' ~ startDispatchCycle
D/InputDispatcher(  277): channel '2c4c2ac8 com.android.systemui.ImageWallpaper (server)' ~ prepareDispatchCycle - flags=0x00000102, xOffset=0.000000, yOffset=0.000000, scaleFactor=1.000000, pointerIds=0x0
D/InputDispatcher(  277): channel '2c4c2ac8 com.android.systemui.ImageWallpaper (server)' ~ startDispatchCycle
D/InputDispatcher(  277): Resetting ANR timeouts.
D/InputDispatcher(  277): channel '2c3a5020 com.android.launcher/com.android.launcher2.Launcher (server)' ~ finishDispatchCycle - seq=31, handled=true
D/InputDispatcher(  277): channel '2c3a5020 com.android.launcher/com.android.launcher2.Launcher (server)' ~ startDispatchCycle
D/InputDispatcher(  277): channel '2c4c2ac8 com.android.systemui.ImageWallpaper (server)' ~ finishDispatchCycle - seq=32, handled=true
D/InputDispatcher(  277): channel '2c4c2ac8 com.android.systemui.ImageWallpaper (server)' ~ startDispatchCycle
D/InputReader(  277): BatchSize: 2 Count: 2
D/InputReader(  277): Input event: device=0 type=0x0001 code=0x014a value=0x00000000 when=716078927000
D/InputReader(  277): Input event: device=0 type=0x0000 code=0x0000 value=0x00000000 when=716078960000
D/InputReader(  277): syncTouch: pointerCount 1 -> 0, touching ids 0x80000000 -> 0x00000000, hovering ids 0x00000000 -> 0x00000000
D/InputDispatcher(  277): notifyMotion - eventTime=716078960000, deviceId=0, source=0x1002, policyFlags=0x0, action=0x1, flags=0x0, metaState=0x0, buttonState=0x0, edgeFlags=0x0, xPrecision=1.000000, yPrecision=1.000000, downTime=716025873000
D/InputDispatcher(  277):   Pointer 0: id=0, toolType=1, x=109.000000, y=329.000000, pressure=1.000000, size=0.000000, touchMajor=0.000000, touchMinor=0.000000, toolMajor=0.000000, toolMinor=0.000000, orientation=0.000000
D/InputDispatcher(  277): Resetting ANR timeouts.
D/InputDispatcher(  277): dispatchMotion - eventTime=716078960000, deviceId=0, source=0x1002, policyFlags=0x42000000, action=0x1, flags=0x0, metaState=0x0, buttonState=0x0, edgeFlags=0x0, xPrecision=1.000000, yPrecision=1.000000, downTime=716025873000
D/InputDispatcher(  277):   Pointer 0: id=0, toolType=1, x=109.000000, y=329.000000, pressure=1.000000, size=0.000000, touchMajor=0.000000, touchMinor=0.000000, toolMajor=0.000000, toolMinor=0.000000, orientation=0.000000
D/InputDispatcher(  277): findTouchedWindow finished: injectionResult=0, injectionPermission=1, timeSpentWaitingForApplication=0.0ms
D/InputDispatcher(  277): dispatchEventToCurrentInputTargets
D/InputDispatcher(  277): channel '2c3a5020 com.android.launcher/com.android.launcher2.Launcher (server)' ~ prepareDispatchCycle - flags=0x00000105, xOffset=0.000000, yOffset=0.000000, scaleFactor=1.000000, pointerIds=0x80000000
D/InputDispatcher(  277): channel '2c3a5020 com.android.launcher/com.android.launcher2.Launcher (server)' ~ startDispatchCycle
D/InputDispatcher(  277): channel '2c4c2ac8 com.android.systemui.ImageWallpaper (server)' ~ prepareDispatchCycle - flags=0x00000102, xOffset=0.000000, yOffset=0.000000, scaleFactor=1.000000, pointerIds=0x0
D/InputDispatcher(  277): channel '2c4c2ac8 com.android.systemui.ImageWallpaper (server)' ~ startDispatchCycle
D/InputDispatcher(  277): Resetting ANR timeouts.
D/InputDispatcher(  277): channel '2c4c2ac8 com.android.systemui.ImageWallpaper (server)' ~ finishDispatchCycle - seq=34, handled=true
D/InputDispatcher(  277): channel '2c4c2ac8 com.android.systemui.ImageWallpaper (server)' ~ startDispatchCycle
D/InputDispatcher(  277): channel '2c3a5020 com.android.launcher/com.android.launcher2.Launcher (server)' ~ finishDispatchCycle - seq=33, handled=true
D/InputDispatcher(  277): channel '2c3a5020 com.android.launcher/com.android.launcher2.Launcher (server)' ~ startDispatchCycle

各位看官看不到出现光圈时事件分发路径的log,没法对比,所以我这里直接解密吧。goldfish上输出的log是正常工作时的log,而跟出现光圈的log对比时,发现出现光圈时捕捉到的事件根本就不是触摸屏的事件,而是鼠标的事件。这里大家要弄明白,输入事件有3种:键盘事件、触摸屏事件、鼠标事件。显然,鼠标事件是在模拟器上才会有的,因为android真实设备还真没见过有用鼠标的。看来,系统是把鼠标输入事件跟触摸屏输入事件混淆了。回去看看第一次贴上的log,好像触摸屏设备真的没有配置好,因为键盘注册时会读取配置文件:

I/EventHub(  723): New device: id=1, fd=80, path='/dev/input/event0', name='ic1-keypad', classes=0x1, configuration='', keyLayout='/system/usr/keylayout/Generic.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm',

但是触摸屏的configuration、keyLayout和keyCharacterMap域都为空:

I/EventHub(  723): New device: id=2, fd=82, path='/dev/input/event1', name='ic1_dano_ts', classes=0x4, configuration='', keyLayout='', keyCharacterMap='',

然后研究了一下EventHub里面读取配置文件的方式,发现是根据设备的名称去找配置文件的。在goldfish中是这样的:

I/EventHub(  277): New device: id=1, fd=97, path='/dev/input/event0', name='qwerty2', classes=0x2d, configuration='/system/usr/idc/qwerty2.idc', keyLayout='/system/usr/keylayout/qwerty.kl', keyCharacterMap='/system/usr/keychars/qwerty2.kcm'

设备的名称为qwerty2,就有对应的qwerty2.idc等文件,这些文件在frameworks/base/data/keyboards/下。所以根据我们触摸屏的设备名字为ic1_dano_ts,参照qwerty2的内容也弄了一个叫ic1_dano_ts.idc的文件,然后编译进去。额,竟然能正常工作了!!既然能正常工作了,所以其它两个域keyLayout和keyCharacterMap就没有再去研究了,如果有了解的看官,可以帮忙解释下。后来,翻了一下资料,发现在android4.0之后加入了一个叫hover的对象,该对象能捕捉鼠标的输入事件,黑色的光圈估计就是这货了!

    好了,到这里,这个bug算是解掉了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值