美文网首页程序员
Android Framework 框架系列之 DisplayM

Android Framework 框架系列之 DisplayM

作者: cff70524f5cf | 来源:发表于2019-01-17 22:30 被阅读41次

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

1.DisplayManagerService的启动

2.DisplayManagerService 作用

3.DisplayManagerService 继承关系

4.DisplayManagerService 的构造方法

5.DisplayManagerService 的onStart 方法

6.DisplayManagerService 的onBootPhase方法

前言

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

frameworks\base\services\java\com\android\server\SystemServer.javaframeworks\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 用来管理显示的生命周期,它决定如何根据当前连接的物理显示设备控制其逻辑显示,并且在状态更改时,向系统和应用程序发送通知,等等。

DisplayAdapter 是 DisplayManagerService 所依赖的集合组件,其为系统显示,收集并发现物理显示设备提供了适配器的作用。

目前有以下两种方式的适配器供使用

一、为本地显示设备提供适配器。

二、为开发者提供的模拟显示适配器。

DisplayAdapter 与 DisplayManagerService 是弱耦合关系。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());

   }

加载本地持久化数据

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. 主要的显示适配器,注册本地适配器lockregisterDisplayAdapterLocked

   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) {

                   }

               }

           }

       }

   }

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

这里提供一份安卓学习思维导图及架构视频资料,需要更加详细的思维导图和资料 关注+加群:185873940 免费获取!

相关文章

网友评论

    本文标题:Android Framework 框架系列之 DisplayM

    本文链接:https://www.haomeiwen.com/subject/exmwdqtx.html