Android开发Android开发经验谈Android技术知识

Android Framework 框架系列之 DisplayM

2019-01-03  本文已影响3人  程序员Android1

极力推荐Android 开发大总结文章:欢迎收藏
程序员Android 力荐 ,Android 开发者需要的必备技能

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

1.DisplayManagerService的启动
2.DisplayManagerService 作用
3.DisplayManagerService 继承关系
4.DisplayManagerService 的构造方法
5.DisplayManagerService 的onStart 方法
6.DisplayManagerService 的onBootPhase(int phase) 方法

前言
本文涉及代码类路径如下,后续涉及代码内容,请参考以下目录。


frameworks\base\services\java\com\android\server\SystemServer.java

frameworks\base\services\core\java\com\android\server\display\DisplayManagerService.java

1.DisplayManagerService的启动

DisplayManagerService 是有 SystemServer
startBootstrapServices 引导阶段中通过startService启动,代码如下:

public final class SystemServer {
    ...

    private void startBootstrapServices() {
        ...
        // Display manager is needed to provide display metrics before package manager
        // starts up.
        traceBeginAndSlog("StartDisplayManager");
        //1.启动 DisplayManagerService
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
        traceEnd();
        ...
     }
    ...

}

2.DisplayManagerService 作用

DisplayManagerService 用来管理显示的生命周期,它决定如何根据当前连接的物理显示设备控制其逻辑显示,并且在状态更改时,向系统和应用程序发送通知,等等。

DisplayAdapterDisplayManagerService 所依赖的集合组件,其为系统显示,收集并发现物理显示设备提供了适配器的作用。
目前有以下两种方式的适配器供使用
一、为本地显示设备提供适配器。
二、为开发者提供的模拟显示适配器。

DisplayAdapterDisplayManagerService 是弱耦合关系。DisplayAdapter通过注册在 DisplayManagerService类中的 DisplayAdapter.Listener 实现异步通信。

这样做有两个原因
一、巧妙地封装了这两个类的职责,
DisplayAdapter :处理各个显示设备
DisplayManagerService:处理全局显示状态。
二、消除异步显示设备发现导致死锁的可能性

Synchronization(同步锁)

因为显示管理器可能被多个线程访问,所以同步锁就会变得有点复杂。 特别是当窗口管理器(window manager)在保持绘制事务的同时调用显示管理器(display manager),窗口管理器期望它可以立即应用并更改。 但不幸的是,显示管理器(display manager)不能异步地做所有事情。
为了解决这个问题,显示管理器的所有对象必须持有相同的锁。 我们将此锁称为同步锁,它具有唯一性。

3.DisplayManagerService 继承关系

DisplayManagerService继承 SystemService, 由 SystemServer 启动。

public final class DisplayManagerService extends SystemService {
   ... 
}

SystemService 是系统Service的基类,相关类使用要重写它的以下生命周期方法(构造方法、onStart() 、onBootPhase(int)),并且所有生命周期内地方法都可以被 system server主线程循环调用。
构造方法
在系统 初始化SystemService的时候被调用。
onStart()方法
Services 运行时候被调用,并且此时需要对外公布Binder接口
publishBinderService(String, IBinder)方法
有时候会同时对外公布本地服务publishLocalService共系统进程调用。
onBootPhase(int)方法
在启动阶段会被调用多次,一直到PHASE_BOOT_COMPLETED
下面DisplayManagerService的使用方法也是按照这个流程来的。

4.DisplayManagerService 的构造方法

DisplayManagerService 构造方法代码如下:

    public DisplayManagerService(Context context) {
        this(context, new Injector());
    }

    @VisibleForTesting
    DisplayManagerService(Context context, Injector injector) {
        super(context);
        mInjector = injector;
        mContext = context;
        // mHandler 用来发送 display 消息
        mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
        mUiHandler = UiThread.getHandler();
        mDisplayAdapterListener = new DisplayAdapterListener();
        mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
        mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
            com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);

        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mGlobalDisplayBrightness = pm.getDefaultScreenBrightnessSetting();
    }

5.DisplayManagerService 的onStart 方法

onStart 主要加载持久化数据(主要是显示设备的宽高等),发送 MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS消息,对外公布Binder、Local Service等。onStart() 方法如下:

   @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 display to register itself with us.
        synchronized(mSyncRoot) {
                        //1. 加载本地持久化数据
            mPersistentDataStore.loadIfNeeded();
            loadStableDisplayValuesLocked();
        }
 // 2. 发送MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS 消息       mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
        //3.对外公布Binder、Local 服务
        publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
                true /*allowIsolated*/);
        publishLocalService(DisplayManagerInternal.class, new LocalService());
        publishLocalService(DisplayTransformManager.class, new DisplayTransformManager());
    }
  1. 加载本地持久化数据
 private void loadIfNeeded() {
        if (!mLoaded) {
            load();
            mLoaded = true;
        }
    }
    private void load() {
        clearState();

        final InputStream is;
        try {
            is = mAtomicFile.openRead();
        } catch (FileNotFoundException ex) {
            return;
        }

        XmlPullParser parser;
        try {
            parser = Xml.newPullParser();
            parser.setInput(new BufferedInputStream(is), StandardCharsets.UTF_8.name());
            loadFromXml(parser);
        } catch (IOException | XmlPullParserException ex) {
            Slog.w(TAG, "Failed to load tv input manager persistent store data.", ex);
            clearState();
        } finally {
            IoUtils.closeQuietly(is);
        }
    }

2.MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS消息 处理方法如下:

  private final class DisplayManagerHandler extends Handler {
        public DisplayManagerHandler(Looper looper) {
            super(looper, null, true /*async*/);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
                    // a.注册默认的显示适配器
                    registerDefaultDisplayAdapters();
                    break;

                case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
                    registerAdditionalDisplayAdapters();
                    break;

         ...
    }

a.registerDefaultDisplayAdapters 实现方法如下:
registerDefaultDisplayAdapters 最主要功能就是将显示设备添加注册到mDisplayAdapters适配器中。

 private void registerDefaultDisplayAdapters() {
        // Register default display adapters.
        synchronized (mSyncRoot) {
            // b. 主要的显示适配器,注册本地适配器lock
            registerDisplayAdapterLocked(new LocalDisplayAdapter(
                    mSyncRoot, mContext, mHandler, mDisplayAdapterListener));

            ...
        }

b. 主要的显示适配器,注册本地适配器lock registerDisplayAdapterLocked

    private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
        mDisplayAdapters.add(adapter);
        adapter.registerLocked();
    }

LocalDisplayAdapter 继承 DisplayAdapter ,主要为本地显示设备提供的适配器。

final class LocalDisplayAdapter extends DisplayAdapter {

   ...
    // Called with SyncRoot lock held.
    public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
            Context context, Handler handler, Listener listener) {
        super(syncRoot, context, handler, listener, TAG);
    }

    // registerDisplayAdapterLocked 中 调用 adapter.registerLocked();
   @Override
    public void registerLocked() {
        super.registerLocked();
       // 1.创建显示设备热插拔时间的监听器
        mHotplugReceiver = new HotplugDisplayEventReceiver(getHandler().getLooper());

        for (int builtInDisplayId : BUILT_IN_DISPLAY_IDS_TO_SCAN) {
            //2.连接显示设备
            tryConnectDisplayLocked(builtInDisplayId);
        }
    }
   
    ...
}

1.创建显示设备热插拔时间的监听器,部分代码如下:

    private final class HotplugDisplayEventReceiver extends DisplayEventReceiver {
        public HotplugDisplayEventReceiver(Looper looper) {
            super(looper, VSYNC_SOURCE_APP);
        }

        @Override
        public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
            synchronized (getSyncRoot()) {
                if (connected) {
                   //连接显示设备
                    tryConnectDisplayLocked(builtInDisplayId);
                } else {
                    tryDisconnectDisplayLocked(builtInDisplayId);
                }
            }
        }
    }

2.连接显示设备,部分代码如下:

    private void tryConnectDisplayLocked(int builtInDisplayId) {
        IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
        if (displayToken != null) {
            SurfaceControl.PhysicalDisplayInfo[] configs =
                    SurfaceControl.getDisplayConfigs(displayToken);
           
            int activeConfig = SurfaceControl.getActiveConfig(displayToken);
            
            int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);

            int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
            LocalDisplayDevice device = mDevices.get(builtInDisplayId);
            if (device == null) {
                // Display was added.
                device = new LocalDisplayDevice(displayToken, builtInDisplayId,
                        configs, activeConfig, colorModes, activeColorMode);
                mDevices.put(builtInDisplayId, device);
                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
            } else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
                        colorModes, activeColorMode)) {
                // Display properties changed.
                sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
            }
        } else {
            // The display is no longer available. Ignore the attempt to add it.
            // If it was connected but has already been disconnected, we'll get a
            // disconnect event that will remove it from mDevices.
        }
    }

然后对 其他services以及app 公开publishBinderService接口

    /**
     * Publish the service so it is accessible to other services and apps.
     */
    protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated) {
        ServiceManager.addService(name, service, allowIsolated);
    }

然后对 系统进程 公开publishLocalService接口

 /**
     * Publish the service so it is only accessible to the system process.
     */
    protected final <T> void publishLocalService(Class<T> type, T service) {
        LocalServices.addService(type, service);
    }

6.DisplayManagerService 的onBootPhase(int phase) 方法

    @Override
    public void onBootPhase(int phase) {
        if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
            synchronized (mSyncRoot) {
                long timeout = SystemClock.uptimeMillis()
                        + mInjector.



                ();
                while (mLogicalDisplays.get(Display.DEFAULT_DISPLAY) == null ||
                        mVirtualDisplayAdapter == null) {
                    long delay = timeout - SystemClock.uptimeMillis();
                    if (delay <= 0) {
                        throw new RuntimeException("Timeout waiting for default display "
                                + "to be initialized. DefaultDisplay="
                                + mLogicalDisplays.get(Display.DEFAULT_DISPLAY)
                                + ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
                    }
                    if (DEBUG) {
                        Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
                    }
                    try {
                        mSyncRoot.wait(delay);
                    } catch (InterruptedException ex) {
                    }
                }
            }
        }
    }
长按识别二维码,领福利

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

如有侵权,请联系小编,小编对此深感抱歉,届时小编会删除文章,立即停止侵权行为,请您多多包涵。

既然都看到这里,领两个红包在走吧!
以下两个红包每天都可以领取

1.支付宝搜索 522398497,或扫码支付宝红包海报。

支付宝扫一扫,每天领取大红包

2.微信红包,微信扫一扫即可领取红包


微信扫一扫,每天领取微信红包
上一篇下一篇

猜你喜欢

热点阅读