DisplayManagerService启动及主屏添加-Android13

DisplayManagerService启动及主屏添加-Android13

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主屏幕添加

AOSP > 文档 > 核心主题 > 显示屏支持

在 Android 11 中, 启动期间报告的第一个屏幕是主屏幕。这与连接类型是内部还是外部并不相关。 不过,主屏幕是不能断开连接的,由此可见,实际操作中的主屏幕必须是内部屏幕。请注意,一些可折叠手机有多个内部屏幕。

辅助屏幕已正确分类为 Display.TYPE_INTERNALDisplay.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 创建DisplayDeviceSurfaceFlinger::setupNewDisplayDeviceInternal
  • DMS 创建DisplayDevice、DisplayDeviceInfotryConnectDisplayLockedgetDisplayDeviceInfoLocked()

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());
}
相关推荐
拭心1 小时前
Google 提供的 Android 端上大模型组件:MediaPipe LLM 介绍
android
带电的小王4 小时前
WhisperKit: Android 端测试 Whisper -- Android手机(Qualcomm GPU)部署音频大模型
android·智能手机·whisper·qualcomm
梦想平凡4 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle
元争栈道4 小时前
webview和H5来实现的android短视频(短剧)音视频播放依赖控件
android·音视频
阿甘知识库5 小时前
宝塔面板跨服务器数据同步教程:双机备份零停机
android·运维·服务器·备份·同步·宝塔面板·建站
元争栈道6 小时前
webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
android·音视频
MuYe6 小时前
Android Hook - 动态加载so库
android
居居飒7 小时前
Android学习(四)-Kotlin编程语言-for循环
android·学习·kotlin
Henry_He10 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗10 小时前
Android笔试面试题AI答之Android基础(1)
android