显示图形系统分析之Java层DisplayDevice和Native层DisplayDevice关联流程

1,635 阅读6分钟

「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。

Java层DisplayDevice和Native层DisplayDevice关联流程

在上一篇默认DisplayDevice显示设备加载流程分析中,我们分析了Native层的DisplayDevice显示设备在SurfaceFlinger中的加载,那么在frameworks的Java层,是如何跟这个DisplayDevice进行关联的呢?

我们知道,安卓系统启动中,通过init进程启动zygote进程后,zygote进程会初始化JAVA世界,Java世界的入口是SystemServer对象,在SystemServer对象中会初始化很多系统服务,其中DisplayManagerService服务就是在此时初始化的

mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

系统启动流程分析中,我们分析过SystemServiceManager.startService函数,可知,在这个函数中主要是做了

  1. 调用DisplayManagerService的单参(Context)构造函数来初始化DisplayManagerService对象
  2. 将上述初始化的DisplayManagerService对象注册到SystemServiceManager.mServices中
  3. 调用DisplayManagerService的onStart函数

如下,我们重点分析第一/三条步骤

DisplayManagerService对象初始化

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

DisplayManagerService(Context context, Injector injector) {
    super(context);
    mInjector = injector;
    mContext = context;
    // 初始化DisplayManagerHandler对象
    // DisplayManagerHandler类继承自Handler类,注意其传入参数为DisplayThread线程的Looper
    mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
    // 获取Handler对象,这边的Handler对象的Looper为UiThread的Looper
    mUiHandler = UiThread.getHandler();
    // 初始化DisplayAdapterListener监听显示设备的变化
    mDisplayAdapterListener = new DisplayAdapterListener();
    // 初始化DisplayModeDirector对象
    mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
    mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
    Resources resources = mContext.getResources();
	// 默认值为0
    mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger(
            com.android.internal.R.integer.config_defaultDisplayDefaultColorMode);
    mDefaultDisplayTopInset = SystemProperties.getInt(PROP_DEFAULT_DISPLAY_TOP_INSET, -1);
    float[] lux = getFloatArray(resources.obtainTypedArray(
            com.android.internal.R.array.config_minimumBrightnessCurveLux));
    float[] nits = getFloatArray(resources.obtainTypedArray(
            com.android.internal.R.array.config_minimumBrightnessCurveNits));
    mMinimumBrightnessCurve = new Curve(lux, nits);
    mMinimumBrightnessSpline = Spline.createSpline(lux, nits);
    // 获取默认背光亮度
    PowerManager pm = mContext.getSystemService(PowerManager.class);
    mGlobalDisplayBrightness = pm.getBrightnessConstraint(
            PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DEFAULT);
    mCurrentUserId = UserHandle.USER_SYSTEM;
    // 从Native层获取data color spaces
    ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
    mWideColorSpace = colorSpaces[1];

    mSystemReady = false;
}

可以看到,在这个函数中主要初始化一些参数,其中的类图关系如下

classDiagram
SystemService <|-- DisplayManagerService
DisplayManagerService o-- Handler
Handler <|-- DisplayModeDirectorHandler
Handler <|-- DisplayManagerHandler
DisplayManagerService o-- DisplayManagerHandler
DisplayManagerService o-- Injector
DisplayManagerService o-- DisplayAdapterListener
DisplayManagerService o-- DisplayModeDirector
Listener <-- DisplayAdapterListener
DisplayAdapter *-- Listener
DisplayModeDirector *-- DisplayModeDirectorHandler
DisplayModeDirector o-- DeviceConfigDisplaySettings
DisplayModeDirector o-- RealInjector
DisplayModeDirector o-- DisplayObserver
DisplayModeDirector o-- BrightnessObserver
DisplayModeDirector o-- SettingsObserver
DisplayModeDirector *-- 2_Injector
OnPropertiesChangedListener <|-- DeviceConfigDisplaySettings
<<interface>> OnPropertiesChangedListener
DeviceConfig *-- OnPropertiesChangedListener
2_Injector <|-- RealInjector
DisplayListener <|-- DisplayObserver
DisplayManager *-- DisplayListener
<<interface>> DisplayListener
ContentObserver <|-- SettingsObserver
ContentObserver <|-- BrightnessObserver
class Injector {
#getVirtualDisplayAdapter(SyncRoot, Context, Handler, DisplayAdapter.Listener)
#getDefaultDisplayDelayTimeout()
}
class DisplayManagerService {
-Injector:mInjector
-Context:mContext
-Handler:mUiHandler
-DisplayManagerHandler:mHandler
-DisplayModeDirector:mDisplayModeDirector
-DisplayAdapterListener:mDisplayAdapterListener
}
class DisplayAdapterListener {
+onDisplayDeviceEvent(DisplayDevice device, int event)
+onTraversalRequested()
}
class UiThread {
-Handler:sHandler
}
class DisplayModeDirector {
-Injector:mInjector
-DisplayModeDirectorHandler:mHandler
-SettingsObserver:mSettingsObserver
-BrightnessObserver:mBrightnessObserver
-DeviceConfigDisplaySettings:mDeviceConfigDisplaySettings
}
class RealInjector {
+getDeviceConfig()
+registerBrightnessObserver(@NonNull ContentResolver, @NonNull ContentObserver
+unregisterBrightnessObserver(@NonNull ContentResolver, @NonNull ContentObserver))
+registerPeakRefreshRateObserver(@NonNull ContentResolver, @NonNull ContentObserver)
}

DisplayManagerService.onStart函数调用

接下来,调用DisplayManagerService的onStart函数来启动服务

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) {
        // 分析对应代码,此处无需关注
        mPersistentDataStore.loadIfNeeded();
        loadStableDisplayValuesLocked();
    }
    // 发送注册默认Display的Adapter
    mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);

    // If there was a runtime restart then we may have stale caches left around, so we need to
    // make sure to invalidate them upon every start.
    DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();

    // 注册BinderService和LocalService到ServiceManager中
    publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
            true /*allowIsolated*/);
    publishLocalService(DisplayManagerInternal.class, new LocalService());
}

如上代码,我们重点需要关注的是注册默认DisplayAdapters

mHandler.sendEmptyMessage(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:
                registerDefaultDisplayAdapters();
                break;
            // ...... 其他分支代码暂时不会进入,此处省略
        }
    }
}

private void registerDefaultDisplayAdapters() {
    // Register default display adapters.
    synchronized (mSyncRoot) {
        // main display adapter
        // 初始化一个LocalDisplayAdapter,然后注册它
        registerDisplayAdapterLocked(new LocalDisplayAdapter(
                mSyncRoot, mContext, mHandler, mDisplayAdapterListener));
        // ...... 虚拟设备,暂时不看,此处省略
    }
}

private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
    // 注册到DisplayManagerService.mDisplayAdapters中
    mDisplayAdapters.add(adapter);
    // 调用LocalDisplayAdapter.registerLocked函数
    adapter.registerLocked();
}

可以看到,此处首先将初始化的LocalDisplayAdapter对象注册到DisplayManagerService.mDisplayAdapter 然后调用LocalDisplayAdapter.registerLocked函数继续注册,看其代码

@Override 
public void registerLocked() {
    super.registerLocked();
    // 初始化一个PhysicalDisplayEventReceiver对象
    // 注意此处的参数为DisplayManagerService.DisplayManagerHandler对象获取到的Looper
    // 响应显示设备变化时的回调函数
    mPhysicalDisplayEventReceiver = new PhysicalDisplayEventReceiver(getHandler().getLooper());
    // 从Naitve层获取到对应的DisplayIds,然后尝试去连接
    for (long physicalDisplayId : SurfaceControl.getPhysicalDisplayIds()) {
        tryConnectDisplayLocked(physicalDisplayId);
    }
}

此处重点看下for循环中具体做了什么

获取Native层的所有显示设备的DisplayId

public static long[] getPhysicalDisplayIds() {
    return nativeGetPhysicalDisplayIds();
}

private static native long[] nativeGetPhysicalDisplayIds();

调用native层的函数nativeGetPhysicalDisplayIds函数,这个函数的注册在

int register_android_view_SurfaceControl(JNIEnv* env)
{
    int err = RegisterMethodsOrDie(env, "android/view/SurfaceControl",
            sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
    // ...... 其他代码和此功能无关,省略
}

static const JNINativeMethod sSurfaceControlMethods[] = {
    // ...... 其他函数和此功能无关,省略
    {"nativeGetPhysicalDisplayIds", "()[J",
            (void*)nativeGetPhysicalDisplayIds },
    // ...... 其他函数和此功能无关,省略
};

static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) {
    // 调用SurfaceComposerClient的getPhysicalDisplayIds函数
    const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds();
    // ...... 其他代码暂时无关,省略
}

std::vector<PhysicalDisplayId> SurfaceComposerClient::getPhysicalDisplayIds() {
    return ComposerService::getComposerService()->getPhysicalDisplayIds();
}

还记得我们此前分析过ComposerService::getComposerService函数么?参见Binder在显示图形系统中的应用 这个函数主要工作是:

  1. ComposerService中包含一个mComposerService参数指向一个BpSurfaceComposer对象,
  2. 这个BpSurfaceComposer对象中包含了一个参数名为mRemote的指针指向的是SurfaceFlinger对象,
  3. 且ComposerService中的BpSurfaceComposer指针对象参数mComposerService和这个ComposerService实现了同生共死状态
  4. 最终ComposerService.getComposerService函数返回的是一个BpSurfaceComposer指针对象

也就是说,此处会调用BpSurfaceComposer指针对象的getPhysicalDisplayIds函数

virtual std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const {
    Parcel data, reply;
    data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
    if (remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS, data, &reply) ==
        NO_ERROR) {
        std::vector<PhysicalDisplayId> displayIds;
        if (reply.readUint64Vector(&displayIds) == NO_ERROR) {
            return displayIds;
        }
    }

    return {};
}

因此,最终会通过BnSurfaceComposer的onTransact函数,调用到SurfaceFlinger的transact函数,来获取对应的DisplayId,从而从Native层中获取到对应的DisplayId,Native层的DisplayId的初始化可以参见默认DisplayDevice显示设备加载流程分析文章 综上,DisplayManagerService对象初始化时注册的DisplayAdapter对象,最终会从Native层的SurfaceFlinger服务中获取到对应的创建的默认显示设备对应的DisplayIds

尝试连接Native层的显示设备

当从Native层获取到DisplayId之后,对应地Java层的DisplayDevice需要和Native层的DisplayDevice进行一一关联,因此需要连接

private void tryConnectDisplayLocked(long physicalDisplayId) {
    // 根据上述的分析,此处调用SurfaceConrol对象的getPhysicalDisplayToken,
    // 最终会调用到Native层的SurfaceFlinger服务,
    // 并通过其getPhysicalDisplayToken函数获取到DisplayDevice的对应BBinder的Key值
    final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
    if (displayToken != null) {
        // 一样地,获取对应的DisplayInfo
        SurfaceControl.DisplayInfo info = SurfaceControl.getDisplayInfo(displayToken);
        // ...... 判空操作,此处不考略,省略
        // 获取显示设备配置
        SurfaceControl.DisplayConfig[] configs = SurfaceControl.getDisplayConfigs(displayToken);
        // ...... 判空操作,此处不考略,省略
        // 获取有效的显示设备配置
        int activeConfig = SurfaceControl.getActiveConfig(displayToken);
        // ...... 判空操作,此处不考略,省略
        // 获取有效的ColorMode
        int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
        // ...... 判空操作,此处不考略,省略
        // 获取Native层显示设备的设备信息
        SurfaceControl.DesiredDisplayConfigSpecs configSpecs =
                SurfaceControl.getDesiredDisplayConfigSpecs(displayToken);
        int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
        Display.HdrCapabilities hdrCapabilities =
                SurfaceControl.getHdrCapabilities(displayToken);
        LocalDisplayDevice device = mDevices.get(physicalDisplayId);
        if (device == null) {
            // Display was added.
            // 同步Native层的显示设备信息到Java层和注册
            final boolean isDefaultDisplay = mDevices.size() == 0;
            device = new LocalDisplayDevice(displayToken, physicalDisplayId, info,
                    configs, activeConfig, configSpecs, colorModes, activeColorMode,
                    hdrCapabilities, isDefaultDisplay);
            mDevices.put(physicalDisplayId, device);
            // 发送显示设备变化事件
            sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
        }
        // ...... 第一次进入无法进入else分支,省略
    }
    // ...... 无关代码,省略
}

可以看到,此处主要将Native层的DisplayDevice信息同步到Java层,并且调用设备添加回调函数,最终会回调DisplayManagerService.DisplayAdapterListener.onDisplayDeviceEvent

private final class DisplayAdapterListener implements DisplayAdapter.Listener {
    @Override
    public void onDisplayDeviceEvent(DisplayDevice device, int event) {
        switch (event) {
            case DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED:
                handleDisplayDeviceAdded(device);
                break;
            ......
        }
    }
    ......
}

private void handleDisplayDeviceAdded(DisplayDevice device) {
    synchronized (mSyncRoot) {
        handleDisplayDeviceAddedLocked(device);
    }
}

private void handleDisplayDeviceAddedLocked(DisplayDevice device) {
    DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
    // ...... 无关代码,省略
    device.mDebugLastLoggedDeviceInfo = info;
    // 注册DisplayDevice信息
    mDisplayDevices.add(device);
    LogicalDisplay display = addLogicalDisplayLocked(device);
    Runnable work = updateDisplayStateLocked(device);
    if (work != null) {
        work.run();
    }
    scheduleTraversalLocked(false);
}

如此,Java层的DisplayDevice和Native层的DisplayDevice就关联在一起了

对应的函数调用关系如下:

DisplayManagerService.onStart函数时序图.png