ViewRoot类的成员函数deliverKeyEventToViewHierarchy首先将参数event所描述的键盘事件交给当前激活的窗口的顶层视图来处理,这是通过调用ViewRoot类的成员变量mView所描述的一个DecorView对象的成员函数dispatchKeyEvent来实现的。

  如果当前激活的窗口的顶层视图在处理完成参数event所描述的键盘事件之后,希望该键盘事件还能继续被ViewRoot类的成员函数deliverKeyEventToViewHierarchy处理,那么前面调用DecorView类的成员函数dispatchKeyEvent得到的返回值keyHandled的值会等于false。在这种情况下,如果参数event描述的是一个按下的键盘事件,即变量isDown的值等于true,那么ViewRoot类的成员函数deliverKeyEventToViewHierarchy会继续检查参数event描述的是否是一个DPAD事件。如果是的话,那么可能需要改变窗口当前的焦点子视图。

  如果参数event描述的是一个DPAD事件,那么终得到的变量direction的值不会等于0,并且它描述的是当前按下的是哪一个方向的DPAD键。假设这时候窗口已经有一个焦点子视图,即调用ViewRoot类的成员变量mView所描述的一个DecorView对象的成员函数findFocus的返回值focused不等于null,那么接下来要根据变量direction的值来决定下一个焦点子视图是谁。例如,假设变量direction的值等于View.FOCUS_LEFT,那么表示在当前的焦点子视图focused的左边查找一个靠近的子视图作为下一个焦点子视图,这是通过调用当前焦点子视图focused的成员函数focusSearch来实现的。

  一旦找到了下一个焦点子视图v,并且该子视图不是当前的焦点子视图focused,那么ViewRoot类的成员函数deliverKeyEventToViewHierarchy需要将子视图v设置为焦点子视图,这是通过调用变量v所描述的一个View对象的成员函数requestFocus来实现的。

  通过前面的操作,参数event所描述的键盘事件处理完成了。如果这时候参数sendDone的值等于true,那么表示需要通知系统的输入管理器,参数event所描述的键盘事件已经处理完成了,这是通过调用ViewRoot类的成员函数finishInputEvent来实现的。

  接下来,我们继续分析DecorView类的成员函数dispatchKeyEvent的实现,以便可以了解窗口的顶层视图分发键盘事件的过程。

  Step 6. DecorView.dispatchKeyEvent

  [java] view plaincopyprint?

  public class PhoneWindow extends Window implements MenuBuilder.Callback {

  ......

  private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {

  ......

  @Override

  public boolean dispatchKeyEvent(KeyEvent event) {

  final int keyCode = event.getKeyCode();

  final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;

  ......

  final Callback cb = getCallback();

  final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)

  : super.dispatchKeyEvent(event);

  if (handled) {

  return true;

  }

  return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)

  : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);

  }

  ......

  }

  ......

  }

  public class PhoneWindow extends Window implements MenuBuilder.Callback {

  ......

  private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {

  ......

  @Override

  public boolean dispatchKeyEvent(KeyEvent event) {

  final int keyCode = event.getKeyCode();

  final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;

  ......

  final Callback cb = getCallback();

  final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)

  : super.dispatchKeyEvent(event);

  if (handled) {

  return true;

  }

  return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)

  : PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);

  }

  ......

  }

  ......

  }

  这个函数定义在文件frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java中。