一、TV应用MainActivity

1.dispatchInputEvent

这里会特殊处理back键,只有Home键才会退出TV应用,back键会传递给cec连接的device处理。如果按键不在黑名单里面,会传递给应用处理。比如音量键就不会传递出去。

    public boolean dispatchKeyEvent(KeyEvent event) {if (SystemProperties.LOG_KEYEVENT.getValue()) Log.d(TAG, "dispatchKeyEvent(" + event + ")");// If an activity is closed on a back key down event, back key down events with none zero// repeat count or a back key up event can be happened without the first back key down// event which should be ignored in this activity.if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {mBackKeyPressed = true;}if (!mBackKeyPressed) {return true;}if (event.getAction() == KeyEvent.ACTION_UP) {mBackKeyPressed = false;}}.......if (BLACKLIST_KEYCODE_TO_TIS.contains(event.getKeyCode())|| KeyEvent.isGamepadButton(event.getKeyCode())) {// If the event is in blacklisted or gamepad key, do not pass it to session.// Gamepad keys are blacklisted to support TV UIs and here's the detail.// If there's a TIS granted RECEIVE_INPUT_EVENT, TIF sends key events to TIS// and return immediately saying that the event is handled.// In this case, fallback key will be injected but with FLAG_CANCELED// while gamepads support DPAD_CENTER and BACK by fallback.// Since we don't expect that TIS want to handle gamepad buttons now,// blacklist gamepad buttons and wait for next fallback keys.// TODO: Need to consider other fallback keys (e.g. ESCAPE)if (SystemProperties.USE_KEY.getValue() || TvSingletons.getSingletons(this).getSystemControlManager().getPropertyBoolean("tv.platform.need_key", false)) {if (event.getAction() == KeyEvent.ACTION_UP) {if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {// It takes long time for TV app to finish, so stop TV first.stopAll(false);super.onBackPressed();return true;}onKeyUp(event.getKeyCode(), event);} else if (event.getAction() == KeyEvent.ACTION_DOWN) {onKeyDown(event.getKeyCode(), event);}return true;} else {return super.dispatchKeyEvent(event);}}return dispatchKeyEventToSession(event) || super.dispatchKeyEvent(event);}

2.dispatchKeyEventToSession

这里主要是把KeyEvent交给TvView处理,因为TvView里面保存着对应的Session。

    private boolean dispatchKeyEventToSession(final KeyEvent event) {if (SystemProperties.LOG_KEYEVENT.getValue()) {Log.d(TAG, "dispatchKeyEventToSession(" + event + ")");}.....boolean handled = false;if (mTvView != null) {handled = mTvView.dispatchKeyEvent(event);}....return handled;}

3.TunableTvView dispatchKeyEvent

只有在正常tune建立session之后才会传递key事件。

    @Overridepublic boolean dispatchKeyEvent(KeyEvent event) {return mCanReceiveInputEvent && mTvView.dispatchKeyEvent(event);}

TvView 下面就是通过session将key event发出去了。

    @Overridepublic boolean dispatchKeyEvent(KeyEvent event) {if (super.dispatchKeyEvent(event)) {return true;}if (DEBUG) Log.d(TAG, "dispatchKeyEvent(" + event + ")");if (mSession == null) {return false;}InputEvent copiedEvent = event.copy();int ret = mSession.dispatchInputEvent(copiedEvent, copiedEvent, mFinishedInputEventCallback,mHandler);return ret != Session.DISPATCH_NOT_HANDLED;}

4.TvInputService.Session

主要是KeyEvent.dispatch,在具体的子类Session里面实现KeyEvent的onKeyDown和onKeyUp来进行处理。

        /*** Takes care of dispatching incoming input events and tells whether the event was handled.*/int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {if (DEBUG) Log.d(TAG, "dispatchInputEvent(" + event + ")");boolean isNavigationKey = false;boolean skipDispatchToOverlayView = false;if (event instanceof KeyEvent) {KeyEvent keyEvent = (KeyEvent) event;if (keyEvent.dispatch(this, mDispatcherState, this)) {return TvInputManager.Session.DISPATCH_HANDLED;}isNavigationKey = isNavigationKey(keyEvent.getKeyCode());// When media keys and KEYCODE_MEDIA_AUDIO_TRACK are dispatched to ViewRootImpl,// ViewRootImpl always consumes the keys. In this case, the application loses// a chance to handle media keys. Therefore, media keys are not dispatched to// ViewRootImpl.skipDispatchToOverlayView = KeyEvent.isMediaKey(keyEvent.getKeyCode())|| keyEvent.getKeyCode() == KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK;} .........}

5.TvInputBaseSession

具体的code不能贴,但后续主要是通过当前的TvClient设备进行KeyEvent的传递。

mTvClient.sendKeyEvent

6.HdmiClient sendKeyEvent

    public void sendKeyEvent(int keyCode, boolean isPressed) {try {mService.sendKeyEvent(getDeviceType(), keyCode, isPressed);} catch (RemoteException e) {Log.e(TAG, "sendKeyEvent threw exception ", e);}}

7.HdmiControlService sendKeyEvent

要通过当前的HdmiCecLocalDevice来发送

        @Overridepublic void sendKeyEvent(final int deviceType, final int keyCode, final boolean isPressed) {enforceAccessPermission();runOnServiceThreadAtFrontOfQueue(new Runnable() {@Overridepublic void run() {Slog.d(TAG, "sendKeyEvent deviceType " + deviceType + " keyCode " + keyCode);....if (mCecController != null) {HdmiCecLocalDevice localDevice = mCecController.getLocalDevice(deviceType);if (localDevice == null) {Slog.w(TAG, "Local device not available");return;}localDevice.sendKeyEvent(keyCode, isPressed);}}});}

8.HdmiCecLocalDevice sendKeyEvent

发起SendKeyAction

    protected void sendKeyEvent(int keyCode, boolean isPressed) {assertRunOnServiceThread();HdmiLogger.debug("sendKeyEvent keyCode:  " + keyCode);if (!HdmiCecKeycode.isSupportedKeycode(keyCode)) {Slog.w(TAG, "Unsupported key: " + keyCode);return;}List<SendKeyAction> action = getActions(SendKeyAction.class);int logicalAddress = findKeyReceiverAddress();if (logicalAddress == Constants.ADDR_INVALID || logicalAddress == mAddress) {// Don't send key event to invalid device or itself.Slog.w(TAG, "Discard key event: " + keyCode + ", pressed:" + isPressed+ ", receiverAddr=" + logicalAddress);} else if (!action.isEmpty()) {action.get(0).processKeyEvent(keyCode, isPressed);} else if (isPressed) {addAndStartAction(new SendKeyAction(this, logicalAddress, keyCode));}}

9.SendKeyAction

这里会将Android的KeyEvent转化成Cec的keyEvent,opcode是MESSAGE_USER_CONTROL_PRESSED即0x44.

比如04 44 02,就表示发送给playback一个向下键。

    /*** Called when a key event should be handled for the action.** @param keycode key code of {@link KeyEvent} object* @param isPressed true if the key event is of {@link KeyEvent#ACTION_DOWN}*/void processKeyEvent(int keycode, boolean isPressed) {if (mState != STATE_CHECKING_LONGPRESS && mState != STATE_PROCESSING_KEYCODE) {Slog.w(TAG, "Not in a valid state");return;}if (isPressed) {// A new key press event that comes in with a key code different from the last// one becomes a new key code to be used for press-and-hold operation.if (keycode != mLastKeycode) {sendKeyDown(keycode);mLastSendKeyTime = getCurrentTime();if (!HdmiCecKeycode.isRepeatableKey(keycode)) {sendKeyUp();finish();return;}} else {// Press-and-hold key transmission takes place if Android key inputs are// repeatedly coming in and more than IRT_MS has passed since the last// press-and-hold key transmission.if (getCurrentTime() - mLastSendKeyTime >= IRT_MS) {sendKeyDown(keycode);mLastSendKeyTime = getCurrentTime();}}mActionTimer.clearTimerMessage();addTimer(mState, AWAIT_RELEASE_KEY_MS);mLastKeycode = keycode;} else {// Key release event indicates that the action shall be finished. Send UCR// command and terminate the action. Other release events are ignored.if (keycode == mLastKeycode) {sendKeyUp();finish();}}}private void sendKeyDown(int keycode) {byte[] cecKeycodeAndParams = HdmiCecKeycode.androidKeyToCecKey(keycode);if (cecKeycodeAndParams == null) {return;}sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(getSourceAddress(),mTargetAddress, cecKeycodeAndParams));}

HdmiCecKeyCode

    // Hdmi CEC keycodespublic static final int CEC_KEYCODE_SELECT = 0x00;public static final int CEC_KEYCODE_UP = 0x01;public static final int CEC_KEYCODE_DOWN = 0x02;public static final int CEC_KEYCODE_LEFT = 0x03;public static final int CEC_KEYCODE_RIGHT = 0x04;public static final int CEC_KEYCODE_RIGHT_UP = 0x05;public static final int CEC_KEYCODE_RIGHT_DOWN = 0x06;public static final int CEC_KEYCODE_LEFT_UP = 0x07;public static final int CEC_KEYCODE_LEFT_DOWN = 0x08;public static final int CEC_KEYCODE_ROOT_MENU = 0x09;public static final int CEC_KEYCODE_SETUP_MENU = 0x0A;public static final int CEC_KEYCODE_CONTENTS_MENU = 0x0B;public static final int CEC_KEYCODE_FAVORITE_MENU = 0x0C;public static final int CEC_KEYCODE_EXIT = 0x0D;// RESERVED = 0x0E - 0x0Fpublic static final int CEC_KEYCODE_MEDIA_TOP_MENU = 0x10;public static final int CEC_KEYCODE_MEDIA_CONTEXT_SENSITIVE_MENU = 0x11;// RESERVED = 0x12 – 0x1Cpublic static final int CEC_KEYCODE_NUMBER_ENTRY_MODE = 0x1D;public static final int CEC_KEYCODE_NUMBER_11 = 0x1E;public static final int CEC_KEYCODE_NUMBER_12 = 0x1F;public static final int CEC_KEYCODE_NUMBER_0_OR_NUMBER_10 = 0x20;public static final int CEC_KEYCODE_NUMBERS_1 = 0x21;public static final int CEC_KEYCODE_NUMBERS_2 = 0x22;public static final int CEC_KEYCODE_NUMBERS_3 = 0x23;public static final int CEC_KEYCODE_NUMBERS_4 = 0x24;public static final int CEC_KEYCODE_NUMBERS_5 = 0x25;public static final int CEC_KEYCODE_NUMBERS_6 = 0x26;public static final int CEC_KEYCODE_NUMBERS_7 = 0x27;public static final int CEC_KEYCODE_NUMBERS_8 = 0x28;public static final int CEC_KEYCODE_NUMBERS_9 = 0x29;public static final int CEC_KEYCODE_DOT = 0x2A;public static final int CEC_KEYCODE_ENTER = 0x2B;public static final int CEC_KEYCODE_CLEAR = 0x2C;// RESERVED = 0x2D - 0x2Epublic static final int CEC_KEYCODE_NEXT_FAVORITE = 0x2F;public static final int CEC_KEYCODE_CHANNEL_UP = 0x30;public static final int CEC_KEYCODE_CHANNEL_DOWN = 0x31;public static final int CEC_KEYCODE_PREVIOUS_CHANNEL = 0x32;public static final int CEC_KEYCODE_SOUND_SELECT = 0x33;public static final int CEC_KEYCODE_INPUT_SELECT = 0x34;public static final int CEC_KEYCODE_DISPLAY_INFORMATION = 0x35;public static final int CEC_KEYCODE_HELP = 0x36;public static final int CEC_KEYCODE_PAGE_UP = 0x37;public static final int CEC_KEYCODE_PAGE_DOWN = 0x38;// RESERVED = 0x39 - 0x3Fpublic static final int CEC_KEYCODE_POWER = 0x40;public static final int CEC_KEYCODE_VOLUME_UP = 0x41;public static final int CEC_KEYCODE_VOLUME_DOWN = 0x42;public static final int CEC_KEYCODE_MUTE = 0x43;public static final int CEC_KEYCODE_PLAY = 0x44;public static final int CEC_KEYCODE_STOP = 0x45;public static final int CEC_KEYCODE_PAUSE = 0x46;public static final int CEC_KEYCODE_RECORD = 0x47;public static final int CEC_KEYCODE_REWIND = 0x48;public static final int CEC_KEYCODE_FAST_FORWARD = 0x49;public static final int CEC_KEYCODE_EJECT = 0x4A;public static final int CEC_KEYCODE_FORWARD = 0x4B;public static final int CEC_KEYCODE_BACKWARD = 0x4C;public static final int CEC_KEYCODE_STOP_RECORD = 0x4D;public static final int CEC_KEYCODE_PAUSE_RECORD = 0x4E;public static final int CEC_KEYCODE_RESERVED = 0x4F;public static final int CEC_KEYCODE_ANGLE = 0x50;public static final int CEC_KEYCODE_SUB_PICTURE = 0x51;public static final int CEC_KEYCODE_VIDEO_ON_DEMAND = 0x52;public static final int CEC_KEYCODE_ELECTRONIC_PROGRAM_GUIDE = 0x53;public static final int CEC_KEYCODE_TIMER_PROGRAMMING = 0x54;public static final int CEC_KEYCODE_INITIAL_CONFIGURATION = 0x55;public static final int CEC_KEYCODE_SELECT_BROADCAST_TYPE = 0x56;public static final int CEC_KEYCODE_SELECT_SOUND_PRESENTATION = 0x57;// RESERVED = 0x58-0x5Fpublic static final int CEC_KEYCODE_PLAY_FUNCTION = 0x60;public static final int CEC_KEYCODE_PAUSE_PLAY_FUNCTION = 0x61;public static final int CEC_KEYCODE_RECORD_FUNCTION = 0x62;public static final int CEC_KEYCODE_PAUSE_RECORD_FUNCTION = 0x63;public static final int CEC_KEYCODE_STOP_FUNCTION = 0x64;public static final int CEC_KEYCODE_MUTE_FUNCTION = 0x65;public static final int CEC_KEYCODE_RESTORE_VOLUME_FUNCTION = 0x66;public static final int CEC_KEYCODE_TUNE_FUNCTION = 0x67;public static final int CEC_KEYCODE_SELECT_MEDIA_FUNCTION = 0x68;public static final int CEC_KEYCODE_SELECT_AV_INPUT_FUNCTION = 0x69;public static final int CEC_KEYCODE_SELECT_AUDIO_INPUT_FUNCTION = 0x6A;public static final int CEC_KEYCODE_POWER_TOGGLE_FUNCTION = 0x6B;public static final int CEC_KEYCODE_POWER_OFF_FUNCTION = 0x6C;public static final int CEC_KEYCODE_POWER_ON_FUNCTION = 0x6D;// RESERVED = 0x6E-0x70public static final int CEC_KEYCODE_F1_BLUE = 0x71;public static final int CEC_KEYCODE_F2_RED = 0x72;public static final int CEC_KEYCODE_F3_GREEN = 0x73;public static final int CEC_KEYCODE_F4_YELLOW = 0x74;public static final int CEC_KEYCODE_F5 = 0x75;public static final int CEC_KEYCODE_DATA = 0x76;

后面就是经过HDMI CEC hal service将cec command发给内核驱动去处理,和其他的cec command的流程没有区别了。

TvInput Cec key事件传递流程相关推荐

  1. Android webkit 事件传递流程

    前言:基于android webview 上定制自己使用的可移植浏览器apk,遇到好多按键处理的问题.所以索***了一下keyevent 事件的传递流程. frameworks 层 keyevent ...

  2. UGUI事件传递流程解析

    很多Unity3D项目都使用了UGUI,但并不是所有人都研究过它的内部结构.针对事件的传递过程,会问住大多数未深入思考过的开发者.由于UGUI是开源的,我们可以通过查看源码来熟悉它的原理,它的地址在可 ...

  3. android touch事件坐标原点,图解Android:Touch事件传递机制

    前言 Android事件管理机制是一名专业Android研发工程师必须要了解的核心知识之一,深入了解一下该机制无论对我们日常开发还是找工作,乃至于对我们的架构思想都有很大的帮助.Android中我们用 ...

  4. Android自定义View2--触摸事件传递机制

    转载文章 :https://juejin.im/post/6844904041487532045#heading-6 https://juejin.im/post/684490389410388378 ...

  5. Android 事件传递机制总结

    Android 事件传递机制总结 Android View虽然不是四大组件,但是其重要程度堪比四大组件.初级工程师到中高级工程师,这些都是很重要的,因为事件分发机制面试也会经常被提及,如果我们能get ...

  6. Android事件传递可以这样理解

    前言 关于Android中事件传递机制早已是老生常谈的话题,甭管工作多久水平咋样应该都能道出一二.依稀记得刚接触事件分发那会,一股脑的钻进网络上那几张神图,什么三大方法.职责链,最后再巴拉巴拉贴一大堆 ...

  7. Android面试必问之触摸事件传递机制

    Android面试必问之触摸事件传递机制 一.Activity的构成 二.触摸事件的类型 三.事件传递的三个阶段 Activity对点击事件的分发过程 五.View的事件分发机制 六.点击事件分发的传 ...

  8. android 事件派发流程详解

    Android 5.0(Lollipop)事件输入系统(Input System) 2014-12-15      23 个评论   来源:世事难料,保持低调   收藏   我要投稿 其实Androi ...

  9. Android Touch事件传递机制 二:单纯的(伪生命周期) 这个清楚一点

    转载于:http://blog.csdn.net/yuanzeyao/article/details/38025165 在前一篇文章中,我主要讲解了Android源码中的Touch事件的传递过程,现在 ...

最新文章

  1. TCP/IP四层模型和OSI七层模型
  2. 如何通过域服务器推送安装文件,域环境推送exe程序并自动安装教程域环境推送exe程序并自动安装教程.pdf...
  3. mq系列传感器的程序_消息中间件(一)MQ详解及四大MQ比较
  4. Java数据结构 反转链表
  5. 编写更好的 Java 单元测试的 7 个技巧
  6. 如何设计高可用的微服务架构
  7. 在centos7中安装redis,并通过node.js操作redis
  8. android开机启动service
  9. 40+张最全Linux/C/C++思维导图,收藏!
  10. Win7下硬盘安装Ubuntu10.10双系统
  11. 推给我的广告都跟我最近看的内容有关系,怎么做到的?
  12. .net开发中常用的第三方组件
  13. gvim配置文件参考
  14. Jetson Nano 读取 GPS数据(TTL转 USB)
  15. linux fastboot 工具下载,FastBoot刷机工具
  16. python进阶小技巧
  17. eclipse安装插件速度很慢的解决方案
  18. 无法通过百度联盟申请的常见原因
  19. AutoCAD打印图纸如何使参照底图灰度显示
  20. matlab单层感知器画线,使用MATLAB编写单层感知器

热门文章

  1. 直播电商源码,简述直播的实现原理
  2. Deep Learning ---Ian Goodfellow
  3. 最新消息凡客诚品卖左旋肉碱了
  4. GBase 8c开发接口(二)
  5. 智能座舱的交互革命,高算力AI芯片赋能全时全域交互体验
  6. 基于JAVAWeb产品管理系统计算机毕业设计源码+数据库+lw文档+系统+部署
  7. 计算机摄像,电脑摄像头工具
  8. 【L2-029 特立独行的幸福】
  9. webapi 开启gzip压缩
  10. win7下运行英雄无敌3的方法