HDMI框架层控制部分别在两个部分:

frameworks/base/core/java/android/hardware/hdmi

frameworks/base/services/core/java/com/android/server/hdmi

 

如果平台是MTK的,

有会一个frameworks/base/services/core/java/com/mediatek/hdmi/MtkHdmiManagerService.java 类,此类有详细的执行操作,此文不做多的解释,

HDMI 首先在PhoneWindowManager中初始化状态

    void initializeHdmiState() {        boolean plugged = false;        // watch for HDMI plug messages if the hdmi switch exists        if (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) {                    }                }            }        }        // 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.        mHdmiPlugged = !plugged;        setHdmiPlugged(!mHdmiPlugged);    }

就是去读state文件,如果连接了电视机则其值为:1,未连接则其值为:0

另外下面代码处是监听HDMI状态值的变化

    private UEventObserver mHDMIObserver = new UEventObserver() {        @Override        public void onUEvent(UEventObserver.UEvent event) {            setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));        }    };

在PhoneWindowManager.java::setInitialDisplaySize()中

SystemProperties.get("persist.demo.hdmirotation"))  是否允许HDMI连接后,竖屏显示,默认空

 mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);  固定屏幕方向默认false,

如果固定HDMI连接屏的显示方向,则会执行下面的执行,

else if (mHdmiPlugged && mDemoHdmiRotationLock) {                // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled.                // Note that the dock orientation overrides the HDMI orientation.                preferredRotation = mDemoHdmiRotation;            } 

mHdmiPlugged 状态为当前机器是否有HDMI连接设备,当前有连接则为true,反之则为false,

HDMIl连接设备对象的信息则是在frameworks\base\services\core\java\com\android\server\display\LocalDisplayAdapter.java中getDisplayDeviceInfoLocked()方法的中的else部分逻辑中生成

                  mInfo.type = Display.TYPE_HDMI;                    mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;                    mInfo.name = getContext().getResources().getString(                            com.android.internal.R.string.display_manager_hdmi_display_name);                    mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;                    mInfo.setAssumedDensityForExternalDisplay(phys.width, phys.height);                    // For demonstration purposes, allow rotation of the external display.                    // In the future we might allow the user to configure this directly.                    if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {                        mInfo.rotation = Surface.ROTATION_270;                    }                    // For demonstration purposes, allow rotation of the external display                    // to follow the built-in display.                    if (SystemProperties.getBoolean("persist.demo.hdmirotates", false)) {                        mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;                    }                    if (!res.getBoolean(                                com.android.internal.R.bool.config_localDisplaysMirrorContent)) {                        mInfo.flags |= DisplayDeviceInfo.FLAG_OWN_CONTENT_ONLY;                    }

另外再看看此类的registerLocked方法

    @Override    public void registerLocked() {        super.registerLocked();        mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());        for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {            tryConnectDisplayLocked(builtInDisplayId);        }    }

BUILD_IN 跟HDMI,built_in可以理解成默认的显示屏,比如手机中默认的MIPI屏,而HDMI则是扩展屏(如电视机),目前在手机上集成HDMI接口的貌似不多,但是usb type c流行后,通过type c来扩展屏幕可能不少,这可能会是一个新的手机定制需求。

    private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {            SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,            SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,    };

DMS中有很多类型的的DisplayAdapter

LocalDisplayAdapter是针对本地已经存在的物理显示屏设备(即HDMI显示)。
WifiDisplayAdapter针对WiFi Display
OverlayDisplayAdapter (这个悬浮显示,在设置-开发者选项-悬浮显示)
VirtualDisplayAdapter 显示一个虚拟屏幕,该功能可以在开发者选项中开启,可以去研究下这个,

DisplayManagerService.java中DMS服务启动之时onStart函数会被调用,这个函数中会外发一个MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER的消息。

    @Override    public void onStart() {        // We need to pre-load the persistent data store so it's ready before the default display        // adapter is up so that we have it's configuration. We could load it lazily, but since        // we're going to have to read it in eventually we may as well do it here rather than after        // we've waited for the diplay to register itself with us.        mPersistentDataStore.loadIfNeeded();        mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTER);        publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),                true /*allowIsolated*/);        publishLocalService(DisplayManagerInternal.class, new LocalService());        publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());    }
    private void registerDefaultDisplayAdapter() {        // Register default display adapter.        synchronized (mSyncRoot) {            registerDisplayAdapterLocked(new LocalDisplayAdapter(//构建一个LocalDisplayAdapter                    mSyncRoot, mContext, mHandler, mDisplayAdapterListener));        }    }

 其它文献:

android graphic(12)—display上层相关概念、关系

Android Display 系统分析

Android Display的初始化

如何获取显示器的EDID信息

Andrdoid6.0 DisplayManagerService

更多相关文章

  1. Android(安卓)share绘制虚线在手机上显示实线问题
  2. TextView显示链接
  3. Android(安卓)学习记录-ImageView显示格式
  4. 【Android】入门级连接网络示例: 网页浏览和播放网络MP3
  5. EditText属性简介
  6. Android——全屏显示的两种方式
  7. android中SharedPreferences和PreferenceActivity的存取数据
  8. ListView使用技巧
  9. 【Android进阶学习】实现没有标题栏的窗口和全屏显示

随机推荐

  1. android的触摸机制
  2. 如何让手机横竖屏切换不重走Activity生命
  3. android下res目录 资源定义及使用
  4. Android短信彩信收发流程(应用层)
  5. android事件处理总结--dispatchTouchEven
  6. Android中6.0及以上悬浮窗申请权限
  7. Appium -GitHub
  8. listview 设置数组为空
  9. Android(安卓)顶部灰条标题栏不显示的方
  10. Android(安卓)LayoutInflater.inflate()