Android Hdmi-CEC 相关文档

A.Android中的HDMI-CEC 背景介绍

B.Android 按键处理流程和HDMI-CEC按键指令的流程分析

C.HDMI-CEC 指令One Touch Play 代码举例

A.android 中HDMI-CEC背景介绍

HDMI-CEC(高清晰度多媒体接口的消费电子控制标准)允许多媒体消费类产品之间沟通和交换信息。HDMI-CEC支持多种功能,例如直通遥控,系统音频控制,其中最常用的是一键播放功能。一键播放功能是指媒体源设备能够打开电视并且让电视自动切换到自己的端口进行播放,这样的话用户就不需要远程控制电视从Chromecast切换到蓝光播放器。

很多厂商采用的HDMI-CEC标准,使他们的产品能够和其他厂商的产品相互工作。但是由于每个厂商实现HDMI-CEC标准的方式不同。很多时候这样的设备之间不能相互理解,而且这些设备还支持不同的功能。由于这种情况,消费者不能简单的认为声称支持CEC的产品之间能够兼容使用。

为了缓解以上描述的设备不能够进行很好的兼容的问题,随着android TIF的引入,HDMI-CEC 能够让相互连接的设备沟通起来,也就是说能够很好的降低设备之间的兼容性问题。Android创建了一个系统服务HdmiControlSerivce来有效缓解这个问题。

HdmiControlSerivce是和系统其他的部分(TIF,Audio服务,电源管理服务)一起来实现CEC标准。

我们从下面两幅图来理解HDMIControlSerivce是怎么缓解兼容性问题的;

图一可以看出,在android5.0之前没有HDMIControlService,对不同设备的兼容和控制都是通过Custom CEC Controller模块来完成(这个可能是厂商自己开发的,或者用第三方的方案),这样所有的兼容性处理工作都放在了Custom CEC Controller模块,里面涉及到显示操作,Audiod 的控制,power的控制,都要通过其来管理,这样使兼容性问题处理起来显得异常复杂,不同设备一多起来,就对Custom CEC Controller模块的健壮性,和扩展性等提高了要求。Android为了解决这个问题(因为google 牛B,所以他才搞),就设计了基于HDMI Control Service服务为核心的一套逻辑,请看图2。从图2中可以看出,HDMI Control Service服务下面添加了HDMI CEC HAL层,这个HAL 层,就是各个使用厂商需要着力开发的部分,里面有一套接口,需要android厂商遵守实现,这样减少了兼容问题的复杂性,只需要在HAL层实现一套接口(下层驱动实现)(接口的定义请看官方文档:https://source.android.google.cn/devices/tv/hdmi-cec),接口里面实现兼容各个HDMI Source设备的指令协议。(仍然是要兼容,但是整体处理兼容问题的工作变得更加公开和便捷,收敛到driver层来解决问题。)而HDMI Control Service服务本身在framework层,可以通过android系统已有的进程间通信机制与TIF ,Audio Service,Power Manager Service进行通信。大大提升了设备之间交互的稳定性等。

B.Android 按键处理流程和HDMI-CEC按键指令的流程分析

  1. 首先我们看一下android系统的按键处理流向

This diagram below shows how buttons on a remote control are passed to a specific TV Input for picture in picture (PIP) display. Those button presses are interpreted by the hardware driver supplied by the device manufacturer,converting hardware scancode to Android keycodes and passing them to the standard Android input pipeline ,InputReader and InputDispatcher functions as KeyEvents.These in turn trigger events on the TV App if it is in focus. PhoneWindowManager接受到这些events后,就dispatch to application. Application 收到相关event后,会有对应的处理逻辑,通过对应的处理逻辑调用函数会执行到下层,进而实现整个event的功能。

1.1下面给出一个例子具体来说明keyEvent是如何被分发的.

上图描述了红键应用的流程,这是欧洲常见的比如MHEG-5(类似于HBBTV)里面应用到的按键(红键)的交互功能。这个应用可以在电视流媒体中传输。当这个键被按下后,可以让用户和这些广播应用交互。例如,你可以用这些广播应用来获取相关网页和比赛结果.

在这个示图中:

  1. TV app 获取了焦点,可以接收所有的输入事件。
  2. KeyEvents(例如红色按钮)被作为InputEvents分发到当前活动的TV Input.
  3. 集成了MHEG-5协议栈的系统级别的TV Input并且具有RECEIVE_INPUT_EVENT权限。
  4. 当收到激活的按键事件(例如红键),TV Input激活广播应用。
  5. TV Input把KeyEvents当成InputEvents,广播应用获得焦点然后处理InputEvents.

注意:第三方的TV inputs不能接收按键事件(只有当前的应用才有接收InputEvents的能力)。

  1. HDMI-CEC指令的相关介绍和执行:

HDMI-CEC允许一个设备来控制其他的设备,这样的话就能够用一个遥控器来控制家庭中的多个设备。这个功能被AndroidTV用来通过集中的TV APP 来加速配置和远程控制各个TV Inputs,例如,可以切换输入源,开关设备等操作。

AndroidTIF 将HDMI-CEC实现为HDMI Control Service.这样的话电视制造商只需要开发底层的驱动,并且和轻量级的androidTV 硬件抽象层交互,不需要关注的复杂的业务层逻辑。为了提供一个标准实现,android通过减少碎片化支持可选择的功能来减少兼容性问题。HDMI Control Service是基于已有的android Service,包括输入和开关机功能。

这意味着现有的HDMI-CEC实现需要重新设计来适配Android TIF,我们推荐在硬件上包含一个微处理器来接受CEC开机指令和其他的命令(这意味着在待机状态有一个微处理芯片在监听CEC设备,如果CEC设备发出指令,微处理器就会和主芯片进行通信,比如唤醒TV)。

  1. CEC总线从当前活动源接收命令切换到一个不同的源。
  2. 驱动将这个命令传给HDMI-CEC硬件抽象层(HAL)。
  3. 硬件抽象层通知所有的ActiveSourceChangeListeners.
  4. HDMI Control Service通过注册ActiveSourceChangeListener被通知源切换。
  5. TV Input Manager Service生成广播来通知TV APP切换输入源。
  6. TV APP 为新的TV Input创建TV Input Manager会话并且在这个会话上调用setMain。
  7. TV Input Manager会话向这个HDMI TV Input发送消息。
  8. HDMI TV Input 请求设置显示界面。
  9. 当界面设置好后。TV Input Manager Service生成相应的切换控制命令回传给HDMI Control Service.

C.HDMI-CEC 指令One Touch Play 代码举例 (在线UML画图邀请链接:https://www.processon.com/i/5e7ec323e4b092510f7ccbb7)

代码架构图

下面两个图以HdmiControlService 为衔接点,上图是说明android HDMI framework对HDMI action的一些封装。下图是Android hdmi framwork,,MTK hdmi framework,以及livetv的衔接情况。

里面跨进程(MTK 的AbstractHdmiTvInputServiceBase进程和HDMIControlService进程)通信衔接利用的方法是onChanged方法.

Android Hdmi framework中 HdmiControlSerivce.java

MTK HDMI framework 层实现的AbstractHdmiTvInputServiceBase.java方法

private final class HdmiInputChangeListener implements InputChangeListener {

@Override

public void onChanged(final HdmiDeviceInfo device) {

runOnServiceThread(new Runnable() {

@Override

public void run() {

if (TvInputConst.DEBUG) {

Log.d(TAG, "HdmiInputChangeListener, onChanged,  device = " + device.toString());

}

String inputId = findInputIdForDeviceInfo(device);

if (inputId == INVALID_INPUT_ID) {

if (TvInputConst.DEBUG) {

Log.e(TAG, "HdmiInputChangeListener, "

+ "onChanged, inputId == INVALID_INPUT_ID, return");

}

return;

}

((HdmiServiceHandler) mHandler).clearTimer(TIMER_DEVICE_SELECT);

if (inputId.equals(mInputContext.inputId)) {

if (TvInputConst.DEBUG) {

Log.d(TAG, "HdmiInputChangeListener, "

+ "onChanged, inputId == (mInputContext.inputId)");

}

AbstractHdmiTvInputSessionImpl session = getCurrentSession(inputId);

// Set the surface deferred from the actual onSetSurface now.

if (session != null) {

/*

* if (hasDeferredSurface(mInputContext)) { if (TvInputConst.DEBUG) { Log.d(TAG,

* "HdmiInputChangeListener, " + "onChanged, (inputId == (mInputContext.inputId)), " +

* "hasDeferredSurface call setSurface"); } session.setSurface(mInputContext.surface);

* }

*/

if (TvInputConst.DEBUG) {

Log.d(TAG, "HdmiInputChangeListener, "

+ "onChanged, (inputId == (mInputContext.inputId))");

}

}

} else {

// A new input change request overwriting the one being anticipated, or

// we were not watching HDMI at all. Request a new input selection to app.

Log.d(TAG, "Tis don't handle one touch play");

if (TvInputConst.DEBUG) {

Log.d(TAG, "HdmiInputChangeListener, "

+ "onChanged, (inputId != (mInputContext.inputId)) ");

}

if (MtkTvScan.getInstance().isScanning()) {

if (TvInputConst.DEBUG) {

Log.d(TAG, "HdmiInputChangeListener"

+ " onChanged: (inputId != (mInputContext.inputId)) isScanning is true, return");

}

return;

}

if (Settings.Secure.getInt(AbstractHdmiTvInputServiceBase.this.getContentResolver(),

Settings.Secure.USER_SETUP_COMPLETE, 0) == 0) {

if (TvInputConst.DEBUG) {

Log.d(TAG, "HdmiInputChangeListener, Ignoring notification: setup not complete");

}

return;

}

mInputContext.reset();

requestInputChange(inputId);

mInputContext.inputId = inputId;

}

}

});

}

private void requestInputChange(String inputId) {

//Log.d(TAG, "requestInputChange=============");

//Intent intent = new Intent(Intent.ACTION_VIEW);

Intent intent = new Intent();

ComponentName componentName = new ComponentName("skyworth.skyworthlivetv","skyworth.skyworthlivetv.osd.ui.mainActivity.LiveTvScreenActivity");

if (isOldProduct()) {

componentName = new ComponentName("skyworth.skyworthlivetv","skyworth.skyworthlivetv.osd.ui.mainActivity.LiveTvScreenActivity");

}else{

componentName = new ComponentName("com.smartdevice.livetv","skyworth.skyworthlivetv.osd.ui.mainActivity.LiveTvScreenActivity");

}

intent.setComponent(componentName);

intent.setAction(Intent.ACTION_VIEW);

intent.setData(TvContract.buildChannelUriForPassthroughInput(inputId));

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.putExtra("livetv", true);

startActivity(intent);

}}

Android HDMI-CEC 知识总结文档相关推荐

  1. Android系统直接输出Excel文档

    Android系统直接输出Excel文档 一.背景 以前Android设备只具备生成txt的能力,数据内容不直观,可读性较差,如果需要Excel文档数据,通常要通过PC软件来进行二次封装和转化,步骤多 ...

  2. 知识管理文档协同不一定要用语雀和石墨,用它效果更好

    随着信息化建设和电子商务时代的到来,企业核心知识资产大多以电子文档的形式存在,保护这些电子文档就是保护企业核心竞争力. 企业知识库可以科学规范化的存储和管理企业的知识资产,换而言之要想提高企业的竞争力 ...

  3. 如何做出有价值的知识管理文档?

    知识管理文档是企业中重要的资产,它可以帮助企业员工更好地理解业务流程.产品功能.标准操作等信息.如何做出有价值的知识管理文档,满足员工知识需求,提高工作效率,本文将探讨以下几个方面: 一.制定有效的知 ...

  4. android app文档,android App项目需求描述文档.docx

    本app是给外卖配送员用的,系统后台根据一定的逻辑生成或者建立运单,本App读到后台的运单讲外卖送到定外卖的手中 本文档所需详细资料请到/s/1jGGgtLG下载 与后台交互的地方不用实现,有数据显示 ...

  5. Android开发人员官方站点文档 - 国内踏得网镜像

    Android Developer 安卓开发人员官方站点无法正常訪问.即使FQ因为网络原因依旧訪问缓慢. 故整理相关字体.脚本.样式.页面资源,在踏得网server上建立了本地镜像.初始镜像时间201 ...

  6. 【Android Gradle 插件】Android Plugin DSL Reference 离线文档下载 ( GitHub 下载文档 | 查看文档 )

    文章目录 一.Android Plugin DSL Reference 文档下载 二.Android Plugin DSL Reference 文档查看 一.Android Plugin DSL Re ...

  7. android内存溢出错误,Android Studio 生成 JavaDoc 空指针异常|文档编码出错|内存溢出...

    一般使用Android Studio生成 JavaDoc会有三个问题: 1.空指针异常 Tools --> Generate JavaDoc -->打开对话框活,在"Other ...

  8. Java游戏开发框架LGame-0 2 8版发布(含JavaSE及Android版,已有文档)

    LGame是LoonFramework框架的一部分,也可简称做"LF"或"Loon". LGame框架的创立初衷在于,构建一个高效且完善的Java游戏开发体系, ...

  9. android studio 如何查看帮助文档

    AS版本:3.5.3 问题描述:Ctrl+Q查看帮助文档时出现 Fetching Documentation,原因是需要科学上网 方案一:下载文档到本地(https://www.cnblogs.com ...

最新文章

  1. 在Mac上使用pip3安装Jupyter Notebook并简单使用
  2. 配置安全的Impala集群集成Sentry
  3. [转]UTF-8 GBK UTF8 GB2312 之间的区别和关系
  4. 简述中断处理的6个步骤_实用!处理电机振动的11个常用步骤
  5. java8 从数组获取流_从数组到流再到Java 8
  6. python接口自动化(三十)--html测试报告通过邮件发出去——中(详解)
  7. CloudStack 4.4+KVM之通过ISO文件创建CentOS虚拟机
  8. 20180914 文件和目录的权限以及属性
  9. 双非二本院校,北京211,字节跳动 → 一个新秀的六年
  10. python-制作手机通讯录导入的vcf格式文件,txt格式转vcf格式
  11. modbus tcp主站和从站_实例分享!西门子PLC通过MODBUS控制变频器
  12. 通过网络使用YAML
  13. Java利用aspose-words将word文档转换成pdf
  14. 高增长神话破灭、巨头围剿“五环外”,拼多多的尽头是“拼夕夕”?
  15. Android 7.0修改分辨率,三星S7升级Android7.0 可调节屏幕分辨率
  16. 张量分解学习(一 基础铺垫)
  17. 弹性盒模型(flex-box)
  18. 汉化软件Radialix 3的使用
  19. Oracle自动化测试工具OATS
  20. H5游戏作弊与防作弊——我如何拿到第一名的天猫精灵

热门文章

  1. mysql ini配置文件分组排序_Windows下的mysql获取my.ini配置文件位置的顺序
  2. 优加DaaS背后,看见新的营销潮
  3. 进击的数据分析:像炒菜一样做策略
  4. 如何取消加密的pdf文件密码?
  5. FLUTTER学习笔记--布局
  6. 《迅为开发板i.MX8MM 学习记录》——【MIPI篇】Linux 应用程序显示一张图片
  7. Litepal 使用时id冲突问题
  8. [多线程]亚马逊图书排名查询
  9. php - php-fpm 启动报错 :Segmentation fault $php_fpm_BIN $php_opts / Gracefully shutting down php(完美解决方案)
  10. 今天的她没有屈服的p2psearcher 2013