`
isiqi
  • 浏览: 15946213 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

android发送模拟按键消息,出现死锁,timeout的解决方法

阅读更多

最近在状态栏上面添加了一些系统常用的按键,用的比较多的,Home, Menu, Back三个按键,

分别模拟物理按键按下时的消息,

参考下面两篇文章,可以实现在状态栏上添加自定义的按键,

1.

在android的状态栏(statusbar)中增加menu,home和back快捷键的方法

http://blogold.chinaunix.net/u2/78893/showart_2349971.html

2.

在android的状态栏(statusbar)中增加menu,home和back快捷键的方法,及按键延迟原因分析

http://hi.baidu.com/tigerpan/blog/item/63caae81b57580b16c811937.html

但是在状态栏上面点击按钮的时候,却经常出现死锁,假死的情况,在第二篇文章的时候,提到,

我们先看一下执行流程
在com.android.server.WindowManagerService.injectKeyEvent(KeyEvent, boolean)函数中我们可以看到实际上是调用dispatchKey(newEvent, pid, uid)函数,这个dispatchKey函数中:

需要先找到当前的焦点focusObj(focusObj:WindowState 就是在维护窗口ViewRoot与WindowManagerService之前的关联,这二者的通信都在WindowState中可以找到);再用focusObj把KeyEvent传递给当前焦点窗口。但在传递之前会先调用mKeyWaiter.waitForNextEventTarget()函数等待当前焦点处理完上一次事件(这包括KeyEvent,MotionEvent...等),如何判断是否处理完上一次事件, 用if (mFinished && !mDisplayFrozen) if (targetWin != null)这两个if语句判断,而最关键就是这个mFinished ,这里还得查看ViewRoot,在ViewRoot中分发事件后会调用sWindowSession.finishKey(mWindow);告诉WindowManagerService,在doFinishedKeyLocked()函数中将mFinished = true,如果mFinished不为true,则会wait(curTimeout),这就是出现停顿的直接原因

通过打印Log显示是我们的KeyEvent.Action_Down事件一直不能mFinished,这就要跟踪ViewRoot,发现每次在模拟的KeyEvent.Action_Down事件的Message根本不能被处理,原因是StatusBarView的TouchEvent没有处理完成,并且与模拟的KeyEvent.Action_Down事件在MessageQueue的next函数中卡住了而ViewRoot本身就是一个Handler,大量的Message从此经过,而StatusBar的ViewRoot既要处理Touch事件也要处理模拟按键,就出现了这种竞态死锁的现象。

延迟发送模拟的KeyEvent是我目前采用的解决方式,上面的例子中sendKey函数已经体现

大概就是按键点击的时候(我自己个人理解),如果在onClick事件里面立刻直接发送KeyEvent的话,会导致onClick的消息处理无法正常返回,从而导致后面的消息也无法被获取处理,这是产生假死停顿的原因,所以参考上面的方法,新创建一个线程,延时发送KeyEvent(我直接用文2的方法问题也没有得到很好的解决).

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics