前言
DisplayManagerService是Android Framework中管理显示屏幕相关的模块,各种Display的连接、配置等,都是通过DMS和来管理控制。
在DMS模块中,对显示屏幕的描述分为物理显示屏(physical display)和逻辑显示屏(logical display),物理屏主要从SurfaceFlinger中读取参数创建,代表实实在在的物理屏,描述其物理特性,不同物理屏有不同的属性。逻辑屏则是相对于对物理屏,侧重于同一个物理屏的不同逻辑设置,受应用和WMS模块影响,如显示区域、显示位置坐标、显示方向等。每一个物理屏幕都对应一个逻辑屏幕,可以修改逻辑屏幕参数,做到同一个物理屏的不同显示方式。
由于不同的物理显示屏有不同的属性和处理方式,因此DMS中通过一系列的屏幕适配器(DisplayAdapter)来和分别各种物理显示屏进行连接。
一、DMS模块常见类
1.1 全局管理类
- IDisplayManager: IBinder接口,负责DMS和其他组建的IPC工作;
- DisplayManagerService:继承于SystemService的系统服务,负责整个系统display的控制和管理;
- DisplayManagerService.LocalService: 继承于DisplayManagerInternal,负责system_server内部其他模块和DMS的交互;
- DisplayManagerService.BindService: 继承于IDisplayManager,是IDisplayManager的具体实现类;
- DisplayManagerService.CallbackRecord: DMS内部类,内部持有IDisplayManagerCallback对象,负责执行IDisplayManagerCallback的回调;
- DisplayManager: 暴露给App层的接口,内部持有DisplayManagerGlobal对象引用,利用DisplayManagerGlobal和DMS进行交互;
- IDisplayManagerCallback:一个IBinder接口,DMS中发生display相关动作后,会通过该接口回调通知给DisplayManagerGlobal;
- DisplayManagerGlobal:内部持有IDisplayManager对象引用,App层通过该对象和DMS进行跨IPC交互;
- DisplayManagerGlobal.DisplayManagerCallback: 继承于IDisplayManagerCallback接口,负责接收来自DMS中display事件的回调;
1.2 数据封装类
- DisplayDevice: 屏幕设备对象。
- DisplayDeviceRepository:屏幕设备管理者,内部持有DisplayDevice集合,负责管理屏幕设备对象。
- WifiDisplayDevice:DisplayDevice的子类,代表通过Wifi连接显示的物理屏幕;
- OverlayDisplayDevice:DisplayDevice的子类,开发者选项->模拟辅助显示开启后,创建的就是该类对象;
- VirtualDisplayDevice:DisplayDevice的子类,表示虚拟显示屏幕,用于屏幕录制等;
- LocalDisplayDevice:DisplayDevice的子类,代表内置物理屏幕,DMS启动后会通过SurfaceControl去读取内置屏幕数据,并创建该类对象;
- LogicalDisplay:代表逻辑显示屏,每一个physical display都会对应一个logical display;
- LogicalDisplayMapper:逻辑屏幕设备管理者,内部持有LogicalDisplay对象集合
- DisplayDeviceInfo: DisplayDevice信息封装类,在创建DisplayDevice时会进行创建,与之对应的是Logical display 的DisplayInfo;
- DisplayInfo:LogicalDisplay信息的封装类,基本数据由DisplayDeviceInfo中获得,app可以通过WMS来修改自己的参数;
- DisplayAdapter: 各物理屏和DMS进行连接的适配器;
- LocalDisplayAdapter: 继承于DisplayAdapter, 用于LocalDisplayDevice和DMS的连接;
- WifiDisplayAdapter: 继承于DisplayAdapter,用于WifiDisplayDevice的和DMS的连接;
- OverlayDisplayAdapter:继承于DisplayAdapter,用于OverlayDisplayDevice和DMS的连接;
- VirtualDisplayAdapter:继承于DisplayAdapter,用于VirtualDisplayDevice和DMS的连接;
- DisplayAdapter.Listener:用于通知DisplayDevice发生变化的接口,DMS中对其进行了实现,会接收以下三个事件并根据事件作出全局反应:a.添加了新的DisplayDevice ;b.DisplayDevice状态发生变化; c.移除DisplayDevice。
- DisplayViewport:携带有physical display参数,用于通知IMS display信息。
1.3 基本类结构的对应关系图
1.4 源码位置
包名 | 目录 | 描述 | 例子 |
---|---|---|---|
android.hardware.display | frameworks/base/core/java/android/hardware/display | DMS模块管理 | DisplayManager, DisplayMangaerGlobal, … |
android.view | frameworks/base/core/java/android/view | 逻辑屏配置项相关 | DisplayInfo, DisplayViewport, … |
com.android.server.display | frameworks/base/services/core/java/com/android/server/display | DMS核心 | DMS,DisplayDevice, … |
二、DisplayManagerService的启动流程
系统启动后会启动JVM虚拟机,SystemServer 是虚拟机的第一个进程,由init 进程fork 产生,主要用来启动frameworks层中的服务,DMS服务也是在这里被启动的,下面我们简单列出SystemServer中和DMS启动相关的源码。
frameworks/base/service/java/com/android/server/SystemServer.java
public final class SystemServer {
private DisplayManagerService mDisplayManagerService;
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
...代码省略...
try {
t.traceBegin("StartServices");
startBootstrapServices(t);//引导服务
startCoreServices(t);//核心服务
startOtherServices(t);//其他服务
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
...代码省略...
}
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
...代码省略...
// Display manager is needed to provide display metrics before package manager
// starts up.
t.traceBegin("StartDisplayManager");
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);//通过反射构建对象实例
t.traceEnd();
// We need the default display before we can initialize the package manager.
t.traceBegin("WaitForDisplay");
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);//调用DMS的onBootPhase方法
t.traceEnd();
...代码省略...
// DisplayManagerService needs to setup android.display scheduling related policies
// since setSystemProcess() would have overridden policies due to setProcessGroup
mDisplayManagerService.setupSchedulerPolicies();//调用DMS的setupSchedulerPolicies方法
...代码省略...
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
...代码省略...
t.traceBegin("DisplayManagerWindowManagerAndInputReady");
mDisplayManagerService.windowManagerAndInputReady();//调用DMS的windowManagerAndInputReady方法
t.traceEnd();
...代码省略...
t.traceBegin("MakeDisplayManagerServiceReady");
try {
mDisplayManagerService.systemReady(safeMode, mOnlyCore);//调用DMS的systemReady方法
} catch (Throwable e) {
reportWtf("making Display Manager Service ready", e);
}
t.traceEnd();
}
}
2.1 构造方法
DisplayManagerService实例对象是通过SystemServiceManager的startService方法获得的,该方法内部先是通过反射构建DisplayManagerService对象实例的,然后还会调用该对象的onStart方法,先来看下构造方法。
frameworks/base/services/core/java/com/android/server/display/DisplayManagerService.java
public final class DisplayManagerService extends SystemService {
private final Context mContext;
//android.display线程的Handler
private final DisplayManagerHandler mHandler;
//android.ui线程Handler
private final Handler mUiHandler;
//主要负责管理和协调设备的显示模式,包括分辨率、刷新率等。
//它优化了系统的显示设置,以平衡性能和电池使用,并确保在多显示器配置下的显示效果一致。
private final DisplayModeDirector mDisplayModeDirector;
//屏幕设备管理者, 此类内容维护了一个 DisplayDevice 对象的集合,这些对象代表了系统中所有的显示设备。
//可以通过这个类跟踪各个显示设备的状态、属性和配置。
private final DisplayDeviceRepository mDisplayDeviceRepo;
//主要负责逻辑显示设备的映射和管理,确保物理显示设备的状态和配置能够正确映射到逻辑显示设备上。
//这个类对于支持多显示器和虚拟显示设备的系统功能至关重要。
private final LogicalDisplayMapper mLogicalDisplayMapper;
private final Injector mInjector;
//负责同步和管理屏幕亮度设置,以确保多个显示设备或显示区域的亮度一致,同时优化用户体验和系统协调。
private final BrightnessSynchronizer mBrightnessSynchronizer;
public DisplayManagerService(Context context) {
this(context, new Injector());
}
@VisibleForTesting
DisplayManagerService(Context context, Injector injector) {
super(context);
mInjector = injector;
mContext = context;
//android.display线程handler
mHandler = new DisplayManagerHandler(DisplayThread.get().getLooper());
//android.ui线程Handler
mUiHandler = UiThread.getHandler();
//管理所有的屏幕设备
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
//负责逻辑显示设备的映射和管理
mLogicalDisplayMapper = new LogicalDisplayMapper(mContext, mDisplayDeviceRepo,
new LogicalDisplayListener(), mSyncRoot, mHandler);
//负责管理和协调设备的显示模式
mDisplayModeDirector = new DisplayModeDirector(context, mHandler);
//负责同步和管理屏幕亮度设置
mBrightnessSynchronizer = new BrightnessSynchronizer(mContext);
Resources resources = mContext.getResources();
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);
mCurrentUserId = UserHandle.USER_SYSTEM;
ColorSpace[] colorSpaces = SurfaceControl.getCompositionColorSpaces();
mWideColorSpace = colorSpaces[1];
mAllowNonNativeRefreshRateOverride = mInjector.getAllowNonNativeRefreshRateOverride();
mSystemReady = false;
}
}
2.2 执行onStart方法
public final class DisplayManagerService extends SystemService {
private final PersistentDataStore mPersistentDataStore = new PersistentDataStore();
@Override
public void onStart() {
// 加载数据
synchronized (mSyncRoot) {
mPersistentDataStore.loadIfNeeded();//加载display中的固定数据
loadStableDisplayValuesLocked();
}
// 在android.display线程中创建默认DisplayAdapter,并进行注册
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();
//向ServiceManager注册BinderService,以便其他模块可以跨进程调用
publishBinderService(Context.DISPLAY_SERVICE, new BinderService(),
true /*allowIsolated*/);
//注册Local Service
publishLocalService(DisplayManagerInternal.class, new LocalService());
}
}
2.2.1 加载display中的固定数据
frameworks/base/services/core/java/com/android/server/display/PersistentDataStore.java
final class PersistentDataStore {
private Injector mInjector;
public PersistentDataStore() {
this(new Injector());
}
@VisibleForTesting
PersistentDataStore(Injector injector) {
mInjector = injector;
}
public void loadIfNeeded() {
if (!mLoaded) {
load();
mLoaded = true;
}
}
private void load() {
clearState();
final InputStream is;
try {
is = mInjector.openRead();
} catch (FileNotFoundException ex) {
return;
}
TypedXmlPullParser parser;
try {
parser = Xml.resolvePullParser(is);
loadFromXml(parser);
} catch (IOException ex) {
Slog.w(TAG, "Failed to load display manager persistent store data.", ex);
clearState();
} catch (XmlPullParserException ex) {
Slog.w(TAG, "Failed to load display manager persistent store data.", ex);
clearState();
} finally {
IoUtils.closeQuietly(is);
}
}
static class Injector {
private final AtomicFile mAtomicFile;
public Injector() {
//display配置的文件路径
mAtomicFile = new AtomicFile(new File("/data/system/display-manager-state.xml"), "display-state");
}
public InputStream openRead() throws FileNotFoundException {
return mAtomicFile.openRead();
}
public OutputStream startWrite() throws IOException {
return mAtomicFile.startWrite();
}
public void finishWrite(OutputStream os, boolean success) {
if (!(os instanceof FileOutputStream)) {
throw new IllegalArgumentException("Unexpected OutputStream as argument: " + os);
}
FileOutputStream fos = (FileOutputStream) os;
if (success) {
mAtomicFile.finishWrite(fos);
} else {
mAtomicFile.failWrite(fos);
}
}
}
}
利用PersistentDataStore加载display中的固定数据,这些数据都是以xml文件的形式,保存在/data/system/display-manager-state.xml中;
2.2.2 注册屏幕适配器
public final class DisplayManagerService extends SystemService {
private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;
@Override
public void onStart() {
...代码省略...
// android.display线程中创建默认DisplayAdapter,并进行注册
mHandler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
...代码省略...
}
private final class DisplayManagerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
//注册默认的屏幕适配器
registerDefaultDisplayAdapters();
break;
case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
//注册额外的屏幕设备适配器
registerAdditionalDisplayAdapters();
break;
...代码省略...
}
}
}
private void registerDefaultDisplayAdapters() {
synchronized (mSyncRoot) {
//注册默认的屏幕适配器
registerDisplayAdapterLocked(new LocalDisplayAdapter(
mSyncRoot, mContext, mHandler, mDisplayDeviceRepo));
//注册虚拟的屏幕适配器
mVirtualDisplayAdapter = mInjector.getVirtualDisplayAdapter(mSyncRoot, mContext,
mHandler, mDisplayDeviceRepo);
if (mVirtualDisplayAdapter != null) {
registerDisplayAdapterLocked(mVirtualDisplayAdapter);
}
}
}
}
2.3 执行onBootPhase方法
DisplayManagerService的onStart()方法被执行完毕后,onBootPhase()方法将会被执行。
public final class DisplayManagerService extends SystemService {
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_WAIT_FOR_DEFAULT_DISPLAY) {
synchronized (mSyncRoot) {
//Injector的getDefaultDisplayDelayTimeout默认返回10秒
long timeout = SystemClock.uptimeMillis() + mInjector.getDefaultDisplayDelayTimeout();
// 超过timeout之后,如果默认屏幕的逻辑显示屏为空,则抛出异常
while (mLogicalDisplayMapper.getDisplayLocked(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="
+ mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY)
+ ", mVirtualDisplayAdapter=" + mVirtualDisplayAdapter);
}
if (DEBUG) {
Slog.d(TAG, "waitForDefaultDisplay: waiting, timeout=" + delay);
}
try {
mSyncRoot.wait(delay);
} catch (InterruptedException ex) {
}
}
}
} else if (phase == PHASE_BOOT_COMPLETED) {
mDisplayModeDirector.onBootCompleted();
}
}
}
PHASE_WAIT_FOR_DEFAULT_DISPLAY阶段是最早的一个启动阶段,当一些引导服务启动完毕后,启动后续服务时,检查DMS是否已经创建默认逻辑屏,如果在10s内没有完成默认LogicalDisplay的创建,则抛出异常。
2.4 执行setupSchedulerPolicies方法
public final class DisplayManagerService extends SystemService {
public void setupSchedulerPolicies() {
// 给android.display、android.anim、android.anim.lf三个线程设置组和CPU集
Process.setThreadGroupAndCpuset(DisplayThread.get().getThreadId(),
Process.THREAD_GROUP_TOP_APP);
Process.setThreadGroupAndCpuset(AnimationThread.get().getThreadId(),
Process.THREAD_GROUP_TOP_APP);
Process.setThreadGroupAndCpuset(SurfaceAnimationThread.get().getThreadId(),
Process.THREAD_GROUP_TOP_APP);
}
}
给以上三个线程设置线程组和调度集,将线程组设为Process.THREAD_GROUP_TOP_APP,以确保更加高效的执行。
2.5 执行windowManagerAndInputReady方法
当SystemServer中启动WindowManagerService和InputManagerService后,将调用此方法通知DMS。
public final class DisplayManagerService extends SystemService {
private static final int MSG_REQUEST_TRAVERSAL = 4;
//WMS和输入法启动完毕
public void windowManagerAndInputReady() {
synchronized (mSyncRoot) {
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
//获取设备状态服务并设置回调对象
DeviceStateManager deviceStateManager = mContext.getSystemService(DeviceStateManager.class);
deviceStateManager.registerCallback(new HandlerExecutor(mHandler), new DeviceStateListener());
//通知WMS进行窗口更新流程
scheduleTraversalLocked(false);
}
}
private void scheduleTraversalLocked(boolean inTraversal) {
if (!mPendingTraversal && mWindowManagerInternal != null) {
mPendingTraversal = true;
if (!inTraversal) {
mHandler.sendEmptyMessage(MSG_REQUEST_TRAVERSAL);
}
}
}
private final class DisplayManagerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
...代码省略...
case MSG_REQUEST_TRAVERSAL:
//通知WMS进行窗口更新流程
mWindowManagerInternal.requestTraversalFromDisplayManager();
break;
...代码省略...
}
}
}
}
先是获得WMS和IMS各自的LocalService对象,然后将发起显示内容更新流程,请求WMS模块进行窗口更新。DMS和WMS联系非常紧密,通常当DMS中相关属性发生变化后,会通知WMS进行窗口更新,WMS在更新过程中也会通知DMS,应用来自窗口的Display相关属性。
2.6 执行systemReady方法
此方法DMS在SystemServer中被调用的最后一个方法,通知DMS启动完成:
public final class DisplayManagerService extends SystemService {
private static final String PROP_DEFAULT_DISPLAY_TOP_INSET = "persist.sys.displayinset.top";
private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;//注册物理屏幕适配器、虚拟屏幕适配器
private static final int MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS = 2;//注册其他屏幕适配器
public void systemReady(boolean safeMode, boolean onlyCore) {
synchronized (mSyncRoot) {
mSafeMode = safeMode;
mOnlyCore = onlyCore;
mSystemReady = true;//启动完成
//将默认Display的top inset存储到persist.sys.displayinset.top中
recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));
updateSettingsLocked();
updateUserDisabledHdrTypesFromSettingsLocked();
}
mDisplayModeDirector.setDesiredDisplayModeSpecsListener(new DesiredDisplayModeSpecsObserver());
mDisplayModeDirector.start(mSensorManager);
//注册除了物理屏幕适配器、虚拟屏幕适配器以外的其他屏幕适配器
mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
mSettingsObserver = new SettingsObserver();
mBrightnessSynchronizer.startSynchronizing();
}
private void recordTopInsetLocked(@Nullable LogicalDisplay d) {
if (!mSystemReady || d == null) {
return;
}
int topInset = d.getInsets().top;
if (topInset == mDefaultDisplayTopInset) {
return;
}
mDefaultDisplayTopInset = topInset;
//将默认Display的top inset存储到persist.sys.displayinset.top中
SystemProperties.set(PROP_DEFAULT_DISPLAY_TOP_INSET, Integer.toString(topInset));
}
private final class DisplayManagerHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS:
//注册默认的屏幕适配器
registerDefaultDisplayAdapters();
break;
case MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS:
//注册额外的屏幕设备适配器
registerAdditionalDisplayAdapters();
break;
...代码省略...
}
}
}
//注册额外的屏幕适配器对象
private void registerAdditionalDisplayAdapters() {
synchronized (mSyncRoot) {
if (shouldRegisterNonEssentialDisplayAdaptersLocked()) {
registerOverlayDisplayAdapterLocked();//注册模拟辅助设备屏幕适配器
registerWifiDisplayAdapterLocked();//注册WIFI屏幕适配器
}
}
}
private void registerOverlayDisplayAdapterLocked() {
registerDisplayAdapterLocked(new OverlayDisplayAdapter(
mSyncRoot, mContext, mHandler, mDisplayDeviceRepo, mUiHandler));
}
private void registerWifiDisplayAdapterLocked() {
if (mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableWifiDisplay)
|| SystemProperties.getInt(FORCE_WIFI_DISPLAY_ENABLE, -1) == 1) {
mWifiDisplayAdapter = new WifiDisplayAdapter(
mSyncRoot, mContext, mHandler, mDisplayDeviceRepo,
mPersistentDataStore);
registerDisplayAdapterLocked(mWifiDisplayAdapter);
}
}
private void registerDisplayAdapterLocked(DisplayAdapter adapter) {
//将适配器对面添加到适配器集合中
mDisplayAdapters.add(adapter);
adapter.registerLocked();
}
}
此方法该会通过mHandler发起注册其他DeviceAdapter的操作,最终完成四种DisplayAdapter的注册。