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

AndroidthreadUP.netHTML
        最近在状态栏上面添加了一些系统常用的按键,用的比较多的,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的方法问题也没有得到很好的解决)。

private void sendVKeyDelay(int key) {
  final int keyCode = key;
    Thread sendKeyDelay = new Thread(){
      public void run() {
         try {
          Thread.sleep(100);
          long now = SystemClock.uptimeMillis();
          KeyEvent keyDown = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode, 0);
          IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
          wm.injectKeyEvent(keyDown, false);

          KeyEvent keyUp = new KeyEvent(now, now, KeyEvent.ACTION_UP, keyCode, 0);
          wm.injectKeyEvent(keyUp, false);

        } catch (InterruptedException e) {
          e.printStackTrace();
        } catch (RemoteException e) {
          e.printStackTrace();
        }
      }
    };
    sendKeyDelay.start();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值