@@ -76,6 +76,7 @@ using aidl::android::hardware::graphics::common::HdrConversionCapability;
7676using aidl::android::hardware::graphics::common::HdrConversionStrategy;
7777using aidl::android::hardware::graphics::composer3::Capability;
7878using aidl::android::hardware::graphics::composer3::DisplayCapability;
79+ using aidl::android::hardware::graphics::composer3::DisplayConfiguration;
7980using namespace std ::string_literals;
8081
8182namespace android {
@@ -222,8 +223,8 @@ bool HWComposer::allocateVirtualDisplay(HalVirtualDisplayId displayId, ui::Size
222223 return true ;
223224}
224225
225- void HWComposer::allocatePhysicalDisplay (hal::HWDisplayId hwcDisplayId,
226- PhysicalDisplayId displayId ) {
226+ void HWComposer::allocatePhysicalDisplay (hal::HWDisplayId hwcDisplayId, PhysicalDisplayId displayId,
227+ std::optional<ui::Size> physicalSize ) {
227228 mPhysicalDisplayIdMap [hwcDisplayId] = displayId;
228229
229230 if (!mPrimaryHwcDisplayId ) {
@@ -235,6 +236,7 @@ void HWComposer::allocatePhysicalDisplay(hal::HWDisplayId hwcDisplayId,
235236 std::make_unique<HWC2::impl::Display>(*mComposer .get (), mCapabilities , hwcDisplayId,
236237 hal::DisplayType::PHYSICAL);
237238 newDisplay->setConnected (true );
239+ newDisplay->setPhysicalSizeInMm (physicalSize);
238240 displayData.hwcDisplay = std::move (newDisplay);
239241}
240242
@@ -276,6 +278,47 @@ std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId d
276278 return getModesFromLegacyDisplayConfigs (hwcDisplayId);
277279}
278280
281+ DisplayConfiguration::Dpi HWComposer::getEstimatedDotsPerInchFromSize (
282+ uint64_t hwcDisplayId, const HWCDisplayMode& hwcMode) const {
283+ if (!FlagManager::getInstance ().correct_dpi_with_display_size ()) {
284+ return {-1 , -1 };
285+ }
286+ if (const auto displayId = toPhysicalDisplayId (hwcDisplayId)) {
287+ if (const auto it = mDisplayData .find (displayId.value ());
288+ it != mDisplayData .end () && it->second .hwcDisplay ->getPhysicalSizeInMm ()) {
289+ ui::Size size = it->second .hwcDisplay ->getPhysicalSizeInMm ().value ();
290+ if (hwcMode.width > 0 && hwcMode.height > 0 && size.width > 0 && size.height > 0 ) {
291+ static constexpr float kMmPerInch = 25 .4f ;
292+ return {hwcMode.width * kMmPerInch / size.width ,
293+ hwcMode.height * kMmPerInch / size.height };
294+ }
295+ }
296+ }
297+ return {-1 , -1 };
298+ }
299+
300+ DisplayConfiguration::Dpi HWComposer::correctedDpiIfneeded (
301+ DisplayConfiguration::Dpi dpi, DisplayConfiguration::Dpi estimatedDpi) const {
302+ // hwc can be unreliable when it comes to dpi. A rough estimated dpi may yield better
303+ // results. For instance, libdrm and bad edid may result in a dpi of {350, 290} for a
304+ // 16:9 3840x2160 display, which would match a 4:3 aspect ratio.
305+ // The logic here checks if hwc was able to provide some dpi, and if so if the dpi
306+ // disparity between the axes is more reasonable than a rough estimate, otherwise use
307+ // the estimated dpi as a corrected value.
308+ if (estimatedDpi.x == -1 || estimatedDpi.x == -1 ) {
309+ return dpi;
310+ }
311+ if (dpi.x == -1 || dpi.y == -1 ) {
312+ return estimatedDpi;
313+ }
314+ if (std::min (dpi.x , dpi.y ) != 0 && std::min (estimatedDpi.x , estimatedDpi.y ) != 0 &&
315+ abs (dpi.x - dpi.y ) / std::min (dpi.x , dpi.y ) >
316+ abs (estimatedDpi.x - estimatedDpi.y ) / std::min (estimatedDpi.x , estimatedDpi.y )) {
317+ return estimatedDpi;
318+ }
319+ return dpi;
320+ }
321+
279322std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromDisplayConfigurations (
280323 uint64_t hwcDisplayId, int32_t maxFrameIntervalNs) const {
281324 std::vector<hal::DisplayConfiguration> configs;
@@ -294,9 +337,16 @@ std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromDisplayConfigura
294337 .configGroup = config.configGroup ,
295338 .vrrConfig = config.vrrConfig };
296339
340+ const DisplayConfiguration::Dpi estimatedDPI =
341+ getEstimatedDotsPerInchFromSize (hwcDisplayId, hwcMode);
297342 if (config.dpi ) {
298- hwcMode.dpiX = config.dpi ->x ;
299- hwcMode.dpiY = config.dpi ->y ;
343+ const DisplayConfiguration::Dpi dpi =
344+ correctedDpiIfneeded (config.dpi .value (), estimatedDPI);
345+ hwcMode.dpiX = dpi.x ;
346+ hwcMode.dpiY = dpi.y ;
347+ } else if (estimatedDPI.x != -1 && estimatedDPI.y != -1 ) {
348+ hwcMode.dpiX = estimatedDPI.x ;
349+ hwcMode.dpiY = estimatedDPI.y ;
300350 }
301351
302352 if (!mEnableVrrTimeout ) {
@@ -328,12 +378,14 @@ std::vector<HWComposer::HWCDisplayMode> HWComposer::getModesFromLegacyDisplayCon
328378
329379 const int32_t dpiX = getAttribute (hwcDisplayId, configId, hal::Attribute::DPI_X);
330380 const int32_t dpiY = getAttribute (hwcDisplayId, configId, hal::Attribute::DPI_Y);
331- if (dpiX != -1 ) {
332- hwcMode.dpiX = static_cast <float >(dpiX) / 1000 .f ;
333- }
334- if (dpiY != -1 ) {
335- hwcMode.dpiY = static_cast <float >(dpiY) / 1000 .f ;
336- }
381+ const DisplayConfiguration::Dpi hwcDpi =
382+ DisplayConfiguration::Dpi{dpiX == -1 ? dpiY : dpiX / 1000 .f ,
383+ dpiY == -1 ? dpiY : dpiY / 1000 .f };
384+ const DisplayConfiguration::Dpi estimatedDPI =
385+ getEstimatedDotsPerInchFromSize (hwcDisplayId, hwcMode);
386+ const DisplayConfiguration::Dpi dpi = correctedDpiIfneeded (hwcDpi, estimatedDPI);
387+ hwcMode.dpiX = dpi.x ;
388+ hwcMode.dpiY = dpi.y ;
337389
338390 modes.push_back (hwcMode);
339391 }
@@ -1072,6 +1124,8 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
10721124 getDisplayIdentificationData (hwcDisplayId, &port, &data);
10731125 if (auto newInfo = parseDisplayIdentificationData (port, data)) {
10741126 info->deviceProductInfo = std::move (newInfo->deviceProductInfo );
1127+ info->preferredDetailedTimingDescriptor =
1128+ std::move (newInfo->preferredDetailedTimingDescriptor );
10751129 } else {
10761130 ALOGE (" Failed to parse identification data for display %" PRIu64, hwcDisplayId);
10771131 }
@@ -1114,7 +1168,11 @@ std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(
11141168 }
11151169
11161170 if (!isConnected (info->id )) {
1117- allocatePhysicalDisplay (hwcDisplayId, info->id );
1171+ std::optional<ui::Size> size = std::nullopt ;
1172+ if (info->preferredDetailedTimingDescriptor ) {
1173+ size = info->preferredDetailedTimingDescriptor ->physicalSizeInMm ;
1174+ }
1175+ allocatePhysicalDisplay (hwcDisplayId, info->id , size);
11181176 }
11191177 return info;
11201178}
0 commit comments