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虚拟机大屏幕设置
  2. Android adb获取屏幕分辨率
  3. Android 获取状态栏的高度
  4. android 中超出屏幕宽度的字符 省略号显示
  5. Android 沉浸式状态栏实现,以及遇到的问题
  6. Android沉浸式状态栏和手机虚拟按钮不兼容冲突的
  7. webview开发-适配多分辨率的Android设备

随机推荐

  1. 在Android程序中使用MQTT
  2. Android Studio 插件之 Android ButterKn
  3. 如何使用Android(安卓)Studio把自己的And
  4. Android 之 自定义标签 和 自定义组件
  5. Android(安卓)利用soap协议与服务端进行
  6. Android在标准linux基础上对休眠唤醒的实
  7. Android数据持久化
  8. android 动画AnimationSet 和 AnimatorSe
  9. 访问自己创建的Contentprovider 抛异常
  10. android application学习之三