安卓11-HDMI插拔检测流程
hdmi从插入到拔出经过底层一系列检测到应用层,应用层获取hdmi插入状态后又会做出一系列相应的动作,下面梳理了从应用层到底层一步步追踪到芯片的hpd-pin的检测过程。
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java +775private class HdmiVideoExtconUEventObserver extends ExtconStateObserver<Boolean> {private static final String HDMI_EXIST = "HDMI=1";private static final String NAME = "hdmi";private final ExtconInfo mHdmi = new ExtconInfo(NAME);private boolean init() {boolean plugged = false;try {plugged = parseStateFromFile(mHdmi);} catch (FileNotFoundException e) {Slog.w(TAG, mHdmi.getStatePath()+ " not found while attempting to determine initial state", e);} catch (IOException e) {Slog.e(TAG,"Error reading " + mHdmi.getStatePath()+ " while attempting to determine initial state",e);}startObserving(mHdmi);return plugged;}@Overridepublic void updateState(ExtconInfo extconInfo, String eventName, Boolean state) {//通过这里更新hdmi plug状态,这个转态来自hal层//这里的变化来自hdmicec_event.cpp mDefaultDisplayPolicy.setHdmiPlugged(state);}@Overridepublic Boolean parseState(ExtconInfo extconIfno, String state) {// extcon event state changes from kernel4.9// new state will be like STATE=HDMI=1return state.contains(HDMI_EXIST);}}void initializeHdmiStateInternal() {boolean plugged = false;// watch for HDMI plug messages if the hdmi switch existsif (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");final String filename = "/sys/class/switch/hdmi/state";FileReader reader = null;try {reader = new FileReader(filename);char[] buf = new char[15];int n = reader.read(buf);if (n > 1) {plugged = 0 != Integer.parseInt(new String(buf, 0, n - 1));}} catch (IOException ex) {Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);} catch (NumberFormatException ex) {Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);} finally {if (reader != null) {try {reader.close();} catch (IOException ex) {}}}} else if (ExtconUEventObserver.extconExists() //走这里 判断sys/class/extcon是否存在&& ExtconUEventObserver.namedExtconDirExists(HdmiVideoExtconUEventObserver.NAME)) {Log.i("fan","xtconUEventObserver.extconExists");HdmiVideoExtconUEventObserver observer = new HdmiVideoExtconUEventObserver();//新建一个hdmi观察者,检测hdmi hpd引脚的变化plugged = observer.init();mHDMIObserver = observer;} else if (localLOGV) {Slog.v(TAG, "Not observing HDMI plug state because HDMI was not found.");}// This dance forces the code in setHdmiPlugged to run.// Always do this so the sticky intent is stuck (to false) if there is no hdmi.mDefaultDisplayPolicy.setHdmiPlugged(plugged, true /* force */);}
frameworks/base/core/java/android/view/WindowManagerPolicyConstants.java:78 String ACTION_HDMI_PLUGGED = "android.intent.action.HDMI_PLUGGED";public void setHdmiPlugged(boolean plugged) {setHdmiPlugged(plugged, false /* force */);}public void setHdmiPlugged(boolean plugged, boolean force) {if (force || mHdmiPlugged != plugged) {mHdmiPlugged = plugged;mService.updateRotation(true /* alwaysSendConfiguration */, true /* forceRelayout */);final Intent intent = new Intent(ACTION_HDMI_PLUGGED);intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);//通知系统hdmi插入状态}}boolean isHdmiPlugged() {return mHdmiPlugged;}
frameworks/base/services/core/java/com/android/server/ExtconUEventObserver.java public static boolean extconExists() {File extconDir = new File("/sys/class/extcon"); //检查这个文件是否存在,对应上面的else if (ExtconUEventObserver.extconExists() return extconDir.exists() && extconDir.isDirectory();}\hardware\rockchip\hdmicec\hdmicec_event.cpp
static void *uevent_loop(void *param)
{hdmi_cec_context_t * ctx = reinterpret_cast<hdmi_cec_context_t *>(param);char thread_name[64] = HDMI_CEC_UEVENT_THREAD_NAME;hdmi_event_t cec_event;struct pollfd pfd[2];int fd[2];int ret, i;prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);fd[0] = ctx->fd;if (fd[0] < 0) {ALOGE ("%s:not able to open cec state node", __func__);return NULL;}pfd[0].fd = fd[0];if (pfd[0].fd >= 0)pfd[0].events = POLLIN | POLLRDNORM | POLLPRI;while (true) {usleep(1000);int err = poll(&pfd[0], 1, 20);if (!err) {continue;} else if(err > 0) {if (!ctx->enable || !ctx->system_control)continue;ALOGD("poll revent:%02x\n", pfd[0].revents);memset(&cec_event, 0, sizeof(hdmi_event_t));if (pfd[0].revents & (POLLIN)) {struct cec_msg cecframe;ALOGD("poll receive msg\n");ret = ioctl(pfd[0].fd, CEC_RECEIVE, &cecframe);if (!ret) {cec_event.type = HDMI_EVENT_CEC_MESSAGE;cec_event.dev = &ctx->device;cec_event.cec.initiator = (cec_logical_address_t)(cecframe.msg[0] >> 4);cec_event.cec.destination = (cec_logical_address_t)(cecframe.msg[0] & 0x0f);cec_event.cec.length = cecframe.len - 1;cec_event.cec.body[0] = cecframe.msg[1];if (!validcecmessage(cec_event)) {for (ret = 0; ret < cec_event.cec.length; ret++)cec_event.cec.body [ret + 1] = cecframe.msg[ret + 2];for (i = 0; i < cecframe.len; i++)ALOGD("poll receive msg[%d]:%02x\n", i, cecframe.msg[i]);if (ctx->event_callback)ctx->event_callback(&cec_event, ctx->cec_arg);} else {ALOGE("%s cec_event length > 15 ", __func__);}} else {ALOGE("%s hdmi cec read error", __FUNCTION__);}}if (pfd[0].revents & (POLLPRI)) {int state = -1;struct cec_event event;ALOGI("poll receive event\n");ret = ioctl(pfd[0].fd, CEC_DQEVENT, &event);//取得一个cec事件,然后判断事件的状态,此部分内容在内核层if (!ret) {ALOGD("event:%d\n", event.event);if (event.event == CEC_EVENT_PIN_HPD_LOW) {//获取底层hpdin管教状态ALOGI("CEC_EVENT_PIN_HPD_LOW\n");ctx->hotplug = false;cec_event.type = HDMI_EVENT_HOT_PLUG;cec_event.dev = &ctx->device;cec_event.hotplug.connected = HDMI_NOT_CONNECTED;cec_event.hotplug.port_id = HDMI_CEC_PORT_ID;if (ctx->event_callback)ctx->event_callback(&cec_event, ctx->cec_arg);} else if (event.event == CEC_EVENT_PIN_HPD_HIGH) {//高为连接ALOGI("CEC_EVENT_PIN_HPD_HIGH\n");ctx->hotplug = true;cec_event.type = HDMI_EVENT_HOT_PLUG;cec_event.dev = &ctx->device;cec_event.hotplug.connected = HDMI_CONNECTED;cec_event.hotplug.port_id = HDMI_CEC_PORT_ID;if (ctx->event_callback)ctx->event_callback(&cec_event, ctx->cec_arg);} else if (event.event == CEC_EVENT_STATE_CHANGE) {ALOGD("adapt state change,phy_addr:%x,flags:%x\n", event.state_change.phys_addr, event.flags);/** Before cec HAL is initialized, hdmi hpd state may be* changed. So we should confirm the hpd status* after cec is initialized(Kernel will report* CEC_EVENT_FL_INITIAL_STATE to notify HAL that* initialization is done).*/if (event.flags & CEC_EVENT_FL_INITIAL_STATE) {ALOGD("cec adapter init complete, get connect state\n");ctx->hotplug = get_hpd_state_from_node(ctx);ctx->cec_init = true;/** Framework will start la polling when box turn on,* In addition, as soon as framewrok receives hdmi* plug in, it will start la polling immediately.* There is not need to report plug in event if hdmi* is connecting when box turn on. So we should report* hdmi plug out only.*/if (!ctx->hotplug)report_hdp_event(ctx, ctx->hotplug);}ctx->phy_addr = event.state_change.phys_addr;}} else {ALOGE("%s cec event get err, ret:%d\n", __func__, ret);}}} else {ALOGE("%s: cec poll failed errno: %s", __FUNCTION__,strerror(errno));continue;}}return NULL;
}Kernel/drivers/media/cec/cec-api.c
static long cec_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)case CEC_DQEVENT:return cec_dqevent(adap, fh, block, parg); //hal层调用这里获取一个cec事件,既然有获取事件就有把时间放入事件队列的地方drivers/media/cec/cec-adap.cvoid cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
{struct cec_event ev = {.event = is_high ? CEC_EVENT_PIN_HPD_HIGH :CEC_EVENT_PIN_HPD_LOW,};struct cec_fh *fh;if (!adap)return;/* hdmi HPD may occur before devnode is registered */if (!adap->devnode.registered)return;mutex_lock(&adap->devnode.lock);list_for_each_entry(fh, &adap->devnode.fhs, list)cec_queue_event_fh(fh, &ev, ktime_to_ns(ts)); //插入一个cec事件,把这个事件放入到ece事件队列,供hal层获取,hal层获取后传到framework层mutex_unlock(&adap->devnode.lock);
}相关文章:
安卓11-HDMI插拔检测流程
hdmi从插入到拔出经过底层一系列检测到应用层,应用层获取hdmi插入状态后又会做出一系列相应的动作,下面梳理了从应用层到底层一步步追踪到芯片的hpd-pin的检测过程。 frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.…...
OkHttp Retrofit HttpClient之间的区别
OkHttp、Retrofit 和 HttpClient 是三个不同的 HTTP 客户端库,它们各自有不同的特点和用途。下面是它们之间的主要区别: 1. **OkHttp**: - OkHttp 是一个高性能的 HTTP 和 HTTP/2 客户端,由 Square 公司开发。 - 它…...
Paddlepaddle使用自己的VOC数据集训练目标检测(0废话简易教程)
一 安装paddlepaddle和paddledection(略) 笔者使用的是自己的数据集 二 在dataset目录下新建自己的数据集文件,如下: 其中 xml文件内容如下: 另外新建一个createList.py文件: # -- coding: UTF-8 -- imp…...
【解析】C语言两个实例
例一: 下面程序输出什么? int main() { int i 43; int n printf("%d\n",i); printf("%d\n",n); return 0; } 大家深入考虑一下为什么返回是3这背后有什么鲜为人知的秘密到底是C语言离奇的规定还是深思熟…...
阅读笔记(Multimedia Systems2020)Review on image-stitching techniques
Wang Z, Yang Z. Review on image-stitching techniques[J]. Multimedia Systems, 2020, 26: 413-430. DOI https://doi.org/10.1007/s00530-020-00651-y...
【Java程序员面试专栏 数据结构】三 高频面试算法题:栈和队列
一轮的算法训练完成后,对相关的题目有了一个初步理解了,接下来进行专题训练,以下这些题目就是汇总的高频题目,因为栈和队列这两哥们结构特性比较向对应,所以放到一篇Blog中集中练习 题目题干直接给出对应博客链接,这里只给出简单思路、代码实现、复杂度分析 题目关键字…...
Python | Conda常用命令
一、介绍 1、Anaconda工具 Anaconda是一个用于数据科学和机器学习的开源软件包管理器和环境管理器。它包含了许多流行的数据科学工具和库,如Python、Jupyter Notebook、numpy、pandas、scikit-learn等,可以帮助用户轻松地管理和安装这些工具和库。Anaco…...
Linux 驱动开发基础知识——APP 怎么读取按键值(十二)
个人名片: 🦁作者简介:学生 🐯个人主页:妄北y 🐧个人QQ:2061314755 🐻个人邮箱:2061314755qq.com 🦉个人WeChat:Vir2021GKBS 🐼本文由…...
【FastAPI】P3 请求与响应
目录 请求路径参数查询参数 响应JSON 响应文本响应返回 Pydantic 模型 在网络通讯中,请求(Request) 与 响应(Response) 扮演着至关重要的角色,它们构成了客户端与服务器间互动的根本理念。 请求࿰…...
Python学习-流程图、分支与循环(branch and loop)
十、流程图 1、流程图(Flowchart) 流程图是一种用于表示算法或代码流程的框图组合,它以不同类型的框框代表不同种类的程序步骤,每两个步骤之间以箭头连接起来。 好处: 1)代码的指导文档 2)有助…...
Python Flask Web 框架学习笔记+完整项目
Flask是一个轻量级的基于Python的web框架。 我们建议使用最新版本的 Python。Flask 支持 Python 3.8 及更高版本。 官网:欢迎使用 Flask — Flask 文档 (3.0.x) (palletsprojects.com) RESTFul API:Python Flask高级编程之REST…...
XML Map 端口进阶篇——常用关键字和格式化器详解
XML Map 端口是用于在不同XML之间建立关系映射的工具,允许通过拖拽操作实现源XML和目标 XML之间的数据字段映射,除此之外,XML Map 端口还提供了其它丰富多彩的功能,使用户能够更加灵活和高效的处理XML 数据映射任务,让…...
排序算法之——直接插入排序
直接插入排序——以升序排列为例 1.1基本思想1.2动态图示感知1.3静态图示详解1.4代码实现1.5时间复杂度1.5.1最好情况1.5.2最差情况 1.6空间复杂度1.7稳定性1.7.1一个小问题 1.1基本思想 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直…...
突出最强算法模型——回归算法 !!
文章目录 1、特征工程的重要性 2、缺失值和异常值的处理 (1)处理缺失值 (2)处理异常值 3、回归模型的诊断 (1)残差分析 (2)检查回归假设 (3)Cooks 距离 4、学…...
云数据库 Redis 性能深度评测(阿里云、华为云、腾讯云、百度智能云)
在当今的云服务市场中,阿里云、腾讯云、华为云和百度智能云都是领先的云服务提供商,他们都提供了全套的云数据库服务,其中 Redis属于RDS 之后第二被广泛应用的服务,本次测试旨在深入比较这四家云服务巨头在Redis云数据库性能方面的…...
Android---Retrofit实现网络请求:Java 版
简介 在 Android 开发中,网络请求是一个极为关键的部分。Retrofit 作为一个强大的网络请求库,能够简化开发流程,提供高效的网络请求能力。 Retrofit 是一个建立在 OkHttp 基础之上的网络请求库,能够将我们定义的 Java 接口转化为…...
使用静态CRLSP配置MPLS TE隧道
正文共:1591 字 13 图,预估阅读时间:4 分钟 静态CRLSP(Constraint-based Routed Label Switched Paths,基于约束路由的LSP)是指在报文经过的每一跳设备上(包括Ingress、Transit和Egress…...
gentoo安装笔记
最近比较闲,所以挑战一下自己,在自己的台式电脑上安装gentoo 下面记录了我亲自安装的步骤,作为以后我再次安装时参考所用。 整体步骤 一般来将一个linux发行版的安装步骤其实大体上都差不多,基本分为一下几步: 1. …...
Git如何使用 五分钟快速入门
Git如何使用 五分钟快速入门 Git是一个分布式版本控制系统,它可以帮助开发人员跟踪和管理项目的代码变更。与传统的集中式版本控制系统(如SVN)不同,Git允许开发人员在本地存储完整的代码仓库,并且可以独立地进行代码修…...
FreeRTOS学习笔记——(FreeRTOS临界段代码保护及调度器挂起与恢复)
这里写目录标题 1,临界段代码保护简介(熟悉)2,临界段代码保护函数介绍(掌握)3,任务调度器的挂起和恢复(熟悉) 1,临界段代码保护简介(熟悉…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
负载均衡器》》LVS、Nginx、HAproxy 区别
虚拟主机 先4,后7...
数据分析六部曲?
引言 上一章我们说到了数据分析六部曲,何谓六部曲呢? 其实啊,数据分析没那么难,只要掌握了下面这六个步骤,也就是数据分析六部曲,就算你是个啥都不懂的小白,也能慢慢上手做数据分析啦。 第一…...
