Android HDMI(三)

7010 ワード

HDMIフレーム層制御部は、それぞれ2つの部分にある.
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/MtkHdmiManagerServices.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接続デバイスオブジェクトの情報はframeworksbaseservicescorejavacomandroidserverdisplayLocalDisplayAdapter.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_MINと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は、開発者オプションで開くことができる仮想スクリーンを表示し、これを検討することができます.
DisplayManagerServices.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