Android HDMI输出设置流程

Android的Surface系统定义了一个DisplayType的枚举,其中有代表手机屏幕的DISPLAY_PRIMARY和代表HDMI等外接设备的DISPLAY_EXTERNAL,还有用于Wi-Fi Display的虚拟显示设备DISPLAY_VIRTUAL。本文就讲解HDMI的输出制式的设置流程。

Android设备通过HDMI线把内容显示到电视机上,当我们开关电视、拔插HDMI线,设置输出制式时,Android系统都做了什么来实现我们的操作?如果由你来设计这个流程,你要怎么实现?看过笔者前面写过的关于Android的网络系统的同仁,熟悉Android系统的代码的人估计很快就会想出Google的工程师应该会怎么实现。首先代码里要有一个HDMI service,这个service用来设置和管理HDMI输出制式,这个service可以是Java的,也可以是C++的,如果是C++说明这个service需要硬件配合实现。当HDMI cable插入后,底层HDMI的驱动检测到(HPD)后,需要通过本地Socket或者其他通信手段把uevent传给HDMI daemon,daemon再把event发送给HDMI service,HDMI daemon和HDMI service的通信不用多说,自然应该是通过Binder机制来实现。HDMI service收到event后做相应的处理来实现用户的操作。

/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

Android系统启动的时候有调用PhoneWindowManager对象的init方法,而该方法里有调用initializeHdmiState(),我们就来分析一下这个

initializeHdmiState()

{

       //这里会创建出一个UEventThread线程来,接收Native层传上来的uevent

       //就是说接收和/devices/virtual/switch/hdmi相关的uevent

       mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");

}

显然这个UEventThread线程就是我们要找的HDMI daemon。

在UEventThread线程的主函数里

/frameworks/base/core/java/android/os/UEventObserver.java

public void run() {

       nativeSetup();

 

       while (true) {

              //不停的接受从Native层传上来的uevent

              Stringmessage = nativeWaitForNextEvent();

              if (message!= null) {

                     //把Message发送给相对应的UEventObserver对象

                     sendEvent(message);

              }

       }

}

nativeWaitForNextEvent()函数是jni接口函数

/frameworks/base/core/jni/android_os_UEventObserver.cpp

static jstring nativeWaitForNextEvent(JNIEnv *env, jclassclazz) {

       for (;;) {

              int length =uevent_next_event(buffer, sizeof(buffer) - 1);

       }

}

/hardware/libhardware_legacy/uevent/uevent.c

int uevent_init()

{

       //在明显不过通过Socket和底层驱动进行通信

       s =socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);

      

       setsockopt(s,SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));

      

       if(bind(s, (structsockaddr *) &addr, sizeof(addr)) < 0) {

             

}

}

int uevent_next_event(char* buffer, int buffer_length)

{

       while (1) {

              //recv接收来自底层驱动的UEvent。

              int count =recv(fd, buffer, buffer_length, 0);

}

}

从上面两个函数来看的话,HDMI daemon其实就是通过Socket和底层驱动进行通信的。

而HDMI的UEventObserver对象就是mHDMIObserver

/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

private UEventObserver mHDMIObserver = new UEventObserver() {

       //处理来自于HDMI daemon的消息

       public voidonUEvent(UEventObserver.UEvent event) {

              setHdmiHwPlugged("1".equals(event.get("SWITCH_STATE")));

       }

};

 

void setHdmiHwPlugged(boolean plugged) {

       if(SystemProperties.getBoolean("ro.platform.has.mbxuimode", false)) {

              if (plugged)

                     mMboxOutputModeManager.setHdmiPlugged();

              else

                     mMboxOutputModeManager.setHdmiUnPlugged();

       }

}

 

/frameworks/base/core/java/android/app/MboxOutputModeManager.java

public void setHdmiPlugged(){

       mService.setHdmiPlugged();

}

其中mService就是MboxOutputModeService对象

MboxOutputModeService是SystemServer里的服务,显然MboxOutputModeService就是我们苦苦寻找的HDMI service。

该服务专门设置盒子的输出制式

/frameworks/base/services/java/com/android/server/MboxOutputModeService.java

public void setHdmiPlugged() {

setOutputMode()

}

public void setOutputModeNowLocked(final String mode){

//把新制式保存到文件/sys/class/display/mode里

//发送广播

}


common/drivers/xxxxx/hdmi/hdmi_tx/hdmi_tx.c

static int amhdmitx_probe(struct platform_device *pdev)

{

       //显然有个线程在不停的处理HDMI相关的事情

       hdmitx_device.task= kthread_run(hdmi_task_handle, &hdmitx_device, "kthread_hdmi");

}

show_disp_cap()

{

       //获取edid

       const char*native_disp_mode = hdmitx_edid_get_native_VIC(&hdmitx_device);

      

       if(hdmitx_device.tv_no_edid){

              //获取不到edid的话,添加"nulledid"

        pos +=snprintf(buf+pos, PAGE_SIZE, "null edid\n");

    } else {

              //正常流程

       }

}

 

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值