DisplayManagerService启动及主屏添加-Android13
- 1、DisplayManagerService启动
-
- [1.1 简要时序图](#1.1 简要时序图)
- 2、DEFAULT_DISPLAY主屏幕添加
-
- [2.1 物理屏热插拔监听](#2.1 物理屏热插拔监听)
- [2.2 物理屏信息](#2.2 物理屏信息)
- 3、默认屏幕亮度
1、DisplayManagerService启动
1.1 简要时序图
代码位置:frameworks/base/services/core/java/com/android/server/display
frameworks/native/services/displayservice
frameworks/native/services/surfaceflinger
1、多屏幕相关:DisplayDeviceRepository.java、LogicalDisplayMapper.java、LocalDisplayAdapter.java、DisplayEventReceiver.java
屏幕类型 静态屏幕标识符 相关类 本地 local:<stable-id> LocalDisplayAdapter.java 网络 network:<mac-address> WifiDisplayAdapter.java 虚拟 virtual:<package-name-and-name> VirtualDisplayAdapter.java 叠加 overlay:<number> OverlayDisplayAdapter.java,开发者选项中模拟辅助显示设备开启 2、屏幕亮度相关:BrightnessSynchronizer.java
2、DEFAULT_DISPLAY主屏幕添加
在 Android 11 中, 启动期间报告的第一个屏幕是主屏幕。这与连接类型是内部还是外部并不相关。 不过,主屏幕是不能断开连接的,由此可见,实际操作中的主屏幕必须是内部屏幕。请注意,一些可折叠手机有多个内部屏幕。
辅助屏幕已正确分类为
Display.TYPE_INTERNAL
或Display.TYPE_EXTERNAL
(以前分别称为 Display.TYPE_BUILT_IN 和 Display.TYPE_HDMI),具体取决于连接类型。在 Android 9 及更低版本中,屏幕使用 32 位 ID 表示 ,其中 0 表示内部屏幕,1 表示外部屏幕,[2, INT32_MAX] 表示 HWC 虚拟屏幕,而 -1 表示无效屏幕或非 HWC 虚拟屏幕。
从 Android 10 开始,屏幕会获得稳定持久的 ID,从而使 SurfaceFlinger 和 DisplayManagerService 可以跟踪两个以上的屏幕并识别以前看到的屏幕。如果 HWC 支持 IComposerClient.getDisplayIdentificationData 并提供屏幕标识数据,SurfaceFlinger 将会解析 EDID 结构并为物理屏幕和 HWC 虚拟屏幕分配稳定的 64 位屏幕 ID。系统会使用选项类型表示 ID,其中 null 值表示无效屏幕或非 HWC 虚拟屏幕。如果 HWC 不支持,SurfaceFlinger 会回退到最多只存在两个物理屏幕的旧版行为。
2.1 物理屏热插拔监听
1、启动注册 LocalDisplayAdapter.registerLocked 时查看添加
tryConnectDisplayLocked(physicalDisplayId)
2、
DisplayEventReceiver
监听添加屏幕tryConnectDisplayLocked(physicalDisplayId)
:
- DisplayEventListener监听注册流程
LocalDisplayAdapter.java#mInjector.setDisplayEventListenerLocked(getHandler().getLooper(), new LocalDisplayEventListener()) > DisplayEventReceiver.java#nativeInit > android_view_DisplayEventReceiver.cpp::nativeInit > DisplayEventDispatcher.cpp::mReceiver > DisplayEventReceiver.cpp::mEventConnection > SurfaceFlinger.cpp::createDisplayEventConnection > Scheduler.cpp::createDisplayEventConnection > EventThread.cpp::createEventConnection > new EventThreadConnection
- DisplayEventReceiver监听接受流程
HWC::onHotplug > SurfaceFlinger.cpp::dispatchDisplayHotplugEvent > Scheduler.cpp::onHotplugReceived > EventThread.cpp::onHotplugReceived > EventThread::threadMain > EventThread::dispatchEvent > EventThreadConnection::postEvent > DisplayEventReceiver.cpp::sendEvents > gui::BitTube::sendObjects(dataChannel, events, count) > ==LooperCallback== DisplayEventDispatcher.cpp::handleEvent > DisplayEventDispatcher::processPendingEvents > android_view_DisplayEventReceiver.cpp::NativeDisplayEventReceiver::dispatchHotplug > LocalDisplayAdapter.java#ProxyDisplayEventReceiver#onHotplug > LocalDisplayEventListener#onHotplug > LocalDisplayAdapter.java#tryConnectDisplayLocked
frameworks/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
java
private void tryConnectDisplayLocked(long physicalDisplayId) {
final IBinder displayToken =
mSurfaceControlProxy.getPhysicalDisplayToken(physicalDisplayId);
if (displayToken != null) {
SurfaceControl.StaticDisplayInfo staticInfo =
mSurfaceControlProxy.getStaticDisplayInfo(displayToken);
if (staticInfo == null) {
Slog.w(TAG, "No valid static info found for display device " + physicalDisplayId);
return;
}
SurfaceControl.DynamicDisplayInfo dynamicInfo =
mSurfaceControlProxy.getDynamicDisplayInfo(displayToken);
if (dynamicInfo == null) {
Slog.w(TAG, "No valid dynamic info found for display device " + physicalDisplayId);
return;
}
if (dynamicInfo.supportedDisplayModes == null) {
// There are no valid modes for this device, so we can't use it
Slog.w(TAG, "No valid modes found for display device " + physicalDisplayId);
return;
}
if (dynamicInfo.activeDisplayModeId < 0) {
// There is no active mode, and for now we don't have the
// policy to set one.
Slog.w(TAG, "No valid active mode found for display device " + physicalDisplayId);
return;
}
if (dynamicInfo.activeColorMode < 0) {
// We failed to get the active color mode. We don't bail out here since on the next
// configuration pass we'll go ahead and set it to whatever it was set to last (or
// COLOR_MODE_NATIVE if this is the first configuration).
Slog.w(TAG, "No valid active color mode for display device " + physicalDisplayId);
dynamicInfo.activeColorMode = Display.COLOR_MODE_INVALID;
}
SurfaceControl.DesiredDisplayModeSpecs modeSpecs =
mSurfaceControlProxy.getDesiredDisplayModeSpecs(displayToken);
LocalDisplayDevice device = mDevices.get(physicalDisplayId);
if (device == null) {
// Display was added.
final boolean isFirstDisplay = mDevices.size() == 0;
device = new LocalDisplayDevice(displayToken, physicalDisplayId, staticInfo,
dynamicInfo, modeSpecs, isFirstDisplay);
mDevices.put(physicalDisplayId, device);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
} else if (device.updateDisplayPropertiesLocked(staticInfo, dynamicInfo,
modeSpecs)) {
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.
}
}
2.2 物理屏信息
硬件插入显示器
HWC::onHotplug
,依赖于Hardware Composer API
。设备制造商必须实现IComposerClient 2.3
HIDL 接口 (android.hardware.graphics.composer@2.3::IComposerClient
) 的getDisplayIdentificationData
方法,或者针对较旧的libhardware
实现情况实现相应的hardware/hwcomposer2.h
函数
sf
创建DisplayDevice :SurfaceFlinger::setupNewDisplayDeviceInternal
DMS
创建DisplayDevice、DisplayDeviceInfo :tryConnectDisplayLocked
、getDisplayDeviceInfoLocked()
frameworks/base/services/core/java/com/android/server/display/DisplayDevice.java
frameworks/base/services/core/java/com/android/server/display/DisplayDeviceInfo.java
frameworks/base/services/core/java/com/android/server/display/LogicalDisplay.java
frameworks/base/core/java/android/view/DisplayInfo.java
DisplayDevice.java | DisplayDeviceInfo.java |
---|---|
IBinder mDisplayToken | String name |
String mUniqueId | String uniqueId |
DisplayDeviceConfig mDisplayDeviceConfig | int width |
int mCurrentLayerStack = -1 | int height |
int mCurrentFlags = 0 | int modeId |
int mCurrentOrientation = -1 | int defaultModeId |
Rect mCurrentLayerStackRect | Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY |
Rect mCurrentDisplayRect | int colorMode |
Context mContext | int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT } |
Surface mCurrentSurface | Display.HdrCapabilities hdrCapabilities |
DisplayDeviceInfo mDebugLastLoggedDeviceInfo | boolean allmSupported |
boolean gameContentTypeSupported | |
int densityDpi | |
float xDpi | |
float yDpi | |
long appVsyncOffsetNanos | |
long presentationDeadlineNanos | |
int flags | |
DisplayCutout displayCutout | |
RoundedCorners roundedCorners | |
int touch | |
int rotation = Surface.ROTATION_0 | |
int type | |
DisplayAddress address | |
DeviceProductInfo deviceProductInfo | |
int state = Display.STATE_ON | |
int ownerUid | |
String ownerPackageName | |
DisplayEventReceiver.FrameRateOverride[] frameRateOverrides = new DisplayEventReceiver.FrameRateOverride[0] | |
float brightnessMinimum | |
float brightnessMaximum | |
float brightnessDefault | |
int installOrientation = Surface.ROTATION_0 |
frameworks/native/libs/ui/include/ui/DisplayIdentification.h
frameworks/native/libs/ui/include/ui/DisplayId.h
frameworks/native/services/surfaceflinger/DisplayDevice.h
frameworks/native/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h
frameworks/native/libs/ui/include/ui/StaticDisplayInfo.h
frameworks/native/libs/ui/include/ui/DynamicDisplayInfo.h
DisplayIdentificationInfo | DisplayDeviceState | DisplayCreationArgs | DisplayDevice | StaticDisplayInfo | DynamicDisplayInfo |
---|---|---|---|---|---|
PhysicalDisplayId id | struct Physical | DisplayId id | constexpr static float sDefaultMinLumiance = 0.0 | DisplayConnectionType connectionType = DisplayConnectionType::Internal | std::vector<ui::DisplayMode> supportedDisplayModes |
std::string name | int32_t sequenceId = sNextSequenceId++ | ui::Size pixels = ui::kInvalidSize | constexpr static float sDefaultMaxLumiance = 500.0 | float density = 0.f | ui::DisplayModeId activeDisplayModeId |
std::optional<DeviceProductInfo> deviceProductInfo | std::optional<Physical> physical | bool isSecure = false | const sp<SurfaceFlinger> mFlinger | bool secure = false | std::vector<ui::ColorMode> supportedColorModes |
sp<IGraphicBufferProducer> surface | Hwc2::PowerAdvisor* powerAdvisor = nullptr | HWComposer& mHwComposer | std::optional<DeviceProductInfo> deviceProductInfo | ||
ui::LayerStack layerStack | std::string name | const wp<IBinder> mDisplayToken | Rotation installOrientation = ROTATION_0 | ui::ColorMode activeColorMode | |
uint32_t flags = 0 | const int32_t mSequenceId | HdrCapabilities hdrCapabilities | |||
Rect layerStackSpaceRect | const std::optional<ui::DisplayConnectionType> mConnectionType | bool autoLowLatencyModeSupported | |||
Rect orientedDisplaySpaceRect | const std::shared_ptr<compositionengine::Display> mCompositionDisplay | bool gameContentTypeSupported | |||
ui::Rotation orientation = ui::ROTATION_0 | std::string mDisplayName | ui::DisplayModeId preferredBootDisplayMode | |||
uint32_t width = 0 | std::string mActiveModeFPSTrace | std::optional<ui::DisplayMode> getActiveDisplayMode() const | |||
uint32_t height = 0 | std::string mActiveModeFPSHwcTrace | ||||
std::string displayName | const ui::Rotation mPhysicalOrientation | ||||
bool isSecure = false | ui::Rotation mOrientation = ui::ROTATION_0 | ||||
static std::atomic<int32_t> sNextSequenceId | static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags | ||||
hardware::graphics::composer::hal::PowerMode mPowerMode = hardware::graphics::composer::hal::PowerMode::OFF | |||||
DisplayModePtr mActiveMode | |||||
std::optional<float> mStagedBrightness = std::nullopt | |||||
float mBrightness = -1.f | |||||
const DisplayModes mSupportedModes | |||||
std::atomic<nsecs_t> mLastHwVsync = 0 | |||||
const bool mIsPrimary | |||||
uint32_t mFlags = 0 | |||||
std::optional<DeviceProductInfo> mDeviceProductInfo | |||||
std::vector<ui::Hdr> mOverrideHdrTypes | |||||
std::shared_ptr<scheduler::RefreshRateConfigs> mRefreshRateConfigs | |||||
std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay | |||||
mutable std::mutex mActiveModeLock | |||||
ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock) | |||||
TracedOrdinal<bool> mDesiredActiveModeChanged GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false} | |||||
ActiveModeInfo mUpcomingActiveMode GUARDED_BY(kMainThreadContext) |
3、默认屏幕亮度
frameworks/base/core/java/com/android/internal/display/BrightnessSynchronizer.java
java
public void startSynchronizing() {
if (mDisplayManager == null) {
mDisplayManager = mContext.getSystemService(DisplayManager.class);
}
if (mBrightnessSyncObserver.isObserving()) {
Slog.wtf(TAG, "Brightness sync observer requesting synchronization a second time.");
return;
}
mLatestFloatBrightness = getScreenBrightnessFloat();
mLatestIntBrightness = getScreenBrightnessInt();
Slog.i(TAG, "Initial brightness readings: " + mLatestIntBrightness + "(int), "
+ mLatestFloatBrightness + "(float)");
if (!Float.isNaN(mLatestFloatBrightness)) {
mPendingUpdate = new BrightnessUpdate(BrightnessUpdate.TYPE_FLOAT,
mLatestFloatBrightness);
} else if (mLatestIntBrightness != PowerManager.BRIGHTNESS_INVALID) {
mPendingUpdate = new BrightnessUpdate(BrightnessUpdate.TYPE_INT,
mLatestIntBrightness);
} else {
final float defaultBrightness = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_screenBrightnessSettingDefaultFloat);
mPendingUpdate = new BrightnessUpdate(BrightnessUpdate.TYPE_FLOAT, defaultBrightness);
Slog.i(TAG, "Setting initial brightness to default value of: " + defaultBrightness);
}
mBrightnessSyncObserver.startObserving();
mHandler.sendEmptyMessageAtTime(MSG_RUN_UPDATE, mClock.uptimeMillis());
}