Android9.0系统HDMI屏幕显示不满

RK Android9.0HDMI屏幕显示不满且分辨率随着lvds分辨率的改变而改变,怎么让HDMI输出全屏显示? 已确认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()

{undefined

   //这里会创建出一个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() {undefined

   nativeSetup();



   while (true) {undefined

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

          Stringmessage = nativeWaitForNextEvent();

          if (message!= null) {undefined

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

                 sendEvent(message);

          }

   }

}

nativeWaitForNextEvent()函数是jni接口函数

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

static jstring nativeWaitForNextEvent(JNIEnv *env, jclassclazz) {undefined

   for (;;) {undefined

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

   }

}

/hardware/libhardware_legacy/uevent/uevent.c

int uevent_init()

{undefined

   //在明显不过通过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) {undefined

         

}

}

int uevent_next_event(char* buffer, int buffer_length)

{undefined

   while (1) {undefined

          //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() {undefined

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

   public voidonUEvent(UEventObserver.UEvent event) {undefined

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

   }

};

void setHdmiHwPlugged(boolean plugged) {undefined

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

          if (plugged)

                 mMboxOutputModeManager.setHdmiPlugged();

          else

                 mMboxOutputModeManager.setHdmiUnPlugged();

   }

}

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

public void setHdmiPlugged(){undefined

   mService.setHdmiPlugged();

}

其中mService就是MboxOutputModeService对象

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

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

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

public void setHdmiPlugged() {undefined

setOutputMode()

}
public void setOutputModeNowLocked(final String mode){undefined

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

//发送广播

}

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

static int amhdmitx_probe(struct platform_device *pdev)

{undefined

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

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

}

show_disp_cap()

{undefined

   //获取edid

   const char*native_disp_mode = hdmitx_edid_get_native_VIC(&hdmitx_device);

  

   if(hdmitx_device.tv_no_edid){undefined

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

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

} else {undefined

          //正常流程

   }

}


   从Android1.6以后的版本都是支持Density这个特性的。
    Density有三组固定不变的值。
   
    Hight Density     240
    Medium Density     160
    Low Density         120


    当在使用Android手机版本软件(Version below 3.0)的时候,由于屏幕尺寸特别大,这个是时候最常见的就是NotificationBar显示不全。
    刚刚开始大家都怀疑是NotificationBar的布局的问题。其实如果是布局的问题,那么应该在任何大小的屏幕上都会有这种问题。
   
    其实大家按照以下步骤就可以了。

1:修改android/frameworks/base/core/java/android/content/res/CompatibilityInfo.java
       
        默认值
       
        DEFAULT_PORTRAIT_WIDTH=320;
        DEFAULT_PORTRAIT_HEIGHT=480;
       
        修改成我们屏幕的实际的默认值。例如我们这里的屏幕大小是1024*600
       
        DEFAULT_PORTRAIT_WIDTH    =    600    ;
        DEFAULT_PORTRAIT_HEIGHT    =    1024;
       
2:
        设置系统默认的ro.sf.lcd_density ,这个里面只能取三组值(240,160,120)。这样在/system/build.prop 我们就可以看见我们结果。
       
       
3:有时候大屏幕还会碰见一个问题,就是应用程序不能完全全屏显示。这个时候,我们还需要处理另外一个问题应用程序的兼容性。
     最直接的方式就是设置应用程序的兼容性为false.这里可以通过DevTool来设置,重启生效。
     通过查找,发现发生作用的地方是在frameworks/base/services/java/com/android/server/PackageManagerService.java
     中
      public void systemReady() {
        mSystemReady = true;
                    //revised by rocky 2010.10.15
        // Read the compatibilty setting when the system is ready.
        boolean compatibilityModeEnabled = android.provider.Settings.System.getInt(
                mContext.getContentResolver(),
                android.provider.Settings.System.COMPATIBILITY_MODE, 0) == 1;
        //PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
        PackageParser.setCompatibilityModeEnabled(false);
        if (DEBUG_SETTINGS) {
            Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
        }
    }
       
        这里我直接设置为false,不取判断保存的设置值。
       
        通过这几个步骤,我相信大尺寸的屏幕显示问题可以得到解决了。

这个可能是你的显示器的纵横比和分辨率不同,要看你的显示器是否支持拉伸显示,你可以看看显示器的说明书。