Android HDMI

您所在的位置:网站首页 管状电机怎样设置遥控器开机启动键功能 Android HDMI

Android HDMI

2024-07-16 09:30:44| 来源: 网络整理| 查看: 265

在OTT设备开发中,经常会遇到个设备状态同步联动需求,比如使用电视遥控器开关电视时,把机顶盒也进行同步开关;反之亦然,开关机顶盒时,电视也同步开关,这样使用一个遥控器就可以控制多个设备,提高用户使用体验。这个功能就需要用到HDMI-CEC协议功能。

android官方相关文档可以查看此处:HDMI-CEC

要实现CEC联动设备功能,前提是机顶盒和电视双方都支持CEC功能,不同的制造商实现上可能有差异,要根据具体设备来看。同时要区分源端和目标端,通常机顶盒等播放设备是源端,电视等显示设备是目标端,固件中通过build.prop属性区分:

源端:

PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=4

目标端:

PRODUCT_PROPERTY_OVERRIDES += ro.hdmi.device_type=0

应用中需要添加cec权限:

我是基于海思Hi3798MV200方案进行开发的,下面均以此平台sdk源码为例简单介绍一下CEC联动过程。

应用层主要关注两个类:HdmiControlManager    HdmiControlService

源码路径:HiSTBAndroidV600R003C00SPC020\frameworks\base\core\java\android\hardware\hdmi\HdmiControlManager.java

HiSTBAndroidV600R003C00SPC020\frameworks\base\services\core\java\com\android\server\hdmi\HdmiControlService.java

所有的应用,都会间接通过HDMIControlManager或者输入通过Tv Input框架间接与HdmiControlService进行通信,HdmiControlService作为SystemServer服务的一个服务,负责处理CEC的命令并与HDMI-CEC HAl进行交互。HAL层和驱动都需要厂商去适配,最后通过CEC总线与CEC设备通信。

基本流程:获取HdmiControlManager对象,通过该对象调用HdmiControlService中的相关方法-检测设备类型源端--检测CEC功能支持--注册监听回调--发送控制命令。

简易示例:

import android.hardware.hdmi.HdmiControlManager; import android.hardware.hdmi.HdmiPlaybackClient; // 获取HdmiControlManager实例 HdmiControlManager hdmiControlManager = (HdmiControlManager) getSystemService(Context.HDMI_CONTROL_SERVICE); // 检查HDMI CEC是否可用 if (hdmiControlManager.isAvailable()) { // 获取HdmiPlaybackClient实例(源端) HdmiPlaybackClient hdmiPlaybackClient = hdmiControlManager.getPlaybackClient(); // 获取HdmiTvClient实例(目标端) // HdmiTvClient hdmiTvClient = hdmiControlManager.getTvClient(); // 检查TV是否处于开机状态 if (hdmiControlManager.getDevicePowerStatus() != HdmiControlManager.POWER_STATUS_ON) { // 发送开机命令 hdmiPlaybackClient.sendStandby(); } else { // 发送关机命令 hdmiPlaybackClient.sendPowerOff(); } }

CEC除了开关机同步,也可以实现各按键功能同步,比如上下左右等功能,还可以设置音量等,除了调用封装好的功能函数,也可以采用发送指令码方式,不同厂商方式有差异,比如海思平台的:

@Override public void setSystemAudioVolume(final int oldIndex, final int newIndex, final int maxIndex) { enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { Slog.w(TAG, "Local tv device not available"); return; } tv.changeVolume(oldIndex, newIndex - oldIndex, maxIndex); } }); } @Override public void setSystemAudioMute(final boolean mute) { enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { Slog.w(TAG, "Local tv device not available"); return; } tv.changeMute(mute); } }); } @Override public void setArcMode(final boolean enabled) { enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { HdmiCecLocalDeviceTv tv = tv(); if (tv == null) { Slog.w(TAG, "Local tv device not available to change arc mode."); return; } } }); } @Override public void setProhibitMode(final boolean enabled) { enforceAccessPermission(); if (!isTvDevice()) { return; } HdmiControlService.this.setProhibitMode(enabled); } @Override public void addVendorCommandListener(final IHdmiVendorCommandListener listener, final int deviceType) { enforceAccessPermission(); HdmiControlService.this.addVendorCommandListener(listener, deviceType); } @Override public void sendVendorCommand(final int deviceType, final int targetAddress, final byte[] params, final boolean hasVendorId) { enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { HdmiCecLocalDevice device = mCecController.getLocalDevice(deviceType); if (device == null) { Slog.w(TAG, "Local device not available"); return; } if (hasVendorId) { sendCecCommand(HdmiCecMessageBuilder.buildVendorCommandWithId( device.getDeviceInfo().getLogicalAddress(), targetAddress, getVendorId(), params)); } else { sendCecCommand(HdmiCecMessageBuilder.buildVendorCommand( device.getDeviceInfo().getLogicalAddress(), targetAddress, params)); } } }); } @Override public void sendStandby(final int deviceType, final int deviceId) { enforceAccessPermission(); runOnServiceThread(new Runnable() { @Override public void run() { HdmiMhlLocalDeviceStub mhlDevice = mMhlController.getLocalDeviceById(deviceId); if (mhlDevice != null) { mhlDevice.sendStandby(); return; } HdmiCecLocalDevice device = mCecController.getLocalDevice(deviceType); if (device == null) { Slog.w(TAG, "Local device not available"); return; } device.sendStandby(deviceId); } }); }

常见的CEC协议指令码:

HDMI-CEC命令是通过特定的操作码(Opcode)来实现的,每个操作码对应一个特定的功能。以下是一些常用的HDMI-CEC命令及其对应的操作码:

1. **One Touch Play**(一键启动)    - `0x04`:Image View On    - `0x34`:Tuner Step Increment (used for one touch record start)    - `0x35`:Tuner Step Decrement (used for one touch record stop)

2. **System Standby**(待机)    - `0x36`:Standby

3. **Preset Transfer** (不是一个典型的CEC命令,通常涉及到多个命令和状态信息的交换)

4. **One Touch Record**    - `0x37`:Record On    - `0x38`:Record Status    - `0x39`:Record Off

5. **Timer Programming** (涉及多个命令,如设置定时器信息)    - `0x97`:Timer Cleared Status    - `0x43`:Timer Status

6. **System Information**    - `0x83`:Give Physical Address    - `0x84`:Report Physical Address    - `0x85`:Request Active Source    - `0x86`:Set Stream Path

7. **Deck Control**    - `0x42`:Deck Control    - `0x1B`:Deck Status

8. **Tuner Control**    - `0x54`:Tuner Device Status    - `0x55`:Give Tuner Device Status    - `0x67`:Tuner Step Increment    - `0x68`:Tuner Step Decrement

9. **Vendor Specific Commands**    - `0x89`:Vendor Command    - `0x8C`:Vendor Remote Button Down    - `0x8D`:Vendor Remote Button Up    - `0x8E`:Give Device Vendor ID    - `0x8F`:Menu Request

10. **Menu Navigation**     - `0x8B`:User Control Pressed     - `0x8C`:User Control Released     - `0x8D`:Give Device Power Status     - `0x8E`:Report Power Status     - `0x0D`:Menu Request     - `0x32`:Set Menu Language

请注意,这些操作码仅是CEC协议中的一部分,而且不同厂商可能会有不同的实现或扩展。要完整地实现CEC功能,还需要考虑具体的设备逻辑地址、参数传递和状态机制等因素。而且,由于CEC协议的实现可能因厂商而异,有时候相同的操作码在不同设备间可能会有不同的行为。如果你需要更详细的信息,通常需要参考HDMI规范的官方文档。

我在实现过程中,通过上述应用层方法没有走通,CEC模块检测通不过,但实际是支持的,好在源码环境开发,我就直接到底层JNI代码中将检测条件去掉了,直接在底层实现相关功能,应用层方法最终也还是调用底层JNI方法的。

HAL层源码位置:

HiSTBAndroidV600R003C00SPC020\device\hisilicon\bigfish\frameworks\hidisplaymanager\hal\hi_adp_hdmi.c

这个是所有HDMI相关控制的中间件层位置,比如分辨率设置、热插拔检测、CEC控制等



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭