Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

package com.facebook.react.uimanager

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.util.DisplayMetrics
Expand Down Expand Up @@ -61,19 +62,21 @@ public object DisplayMetricsHolder {
}

@JvmStatic
@Suppress("DEPRECATION")
@SuppressLint("DeprecatedMethod") // for Andriod Lint
@Suppress("DEPRECATION") // for Kotlin compiler
public fun initDisplayMetrics(context: Context) {
val displayMetrics = context.resources.displayMetrics
windowDisplayMetrics = displayMetrics
val screenDisplayMetrics = DisplayMetrics()
screenDisplayMetrics.setTo(displayMetrics)
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
// Get the real display metrics if we are using API level 17 or higher.
// The real metrics include system decor elements (e.g. soft menu bar).
//
// See:
// http://developer.android.com/reference/android/view/Display.html#getRealMetrics(android.util.DisplayMetrics)
wm.defaultDisplay.getRealMetrics(screenDisplayMetrics)
try {
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
// getRealMetrics includes system decor (e.g. nav bar) excluded from resource metrics.
wm.defaultDisplay.getRealMetrics(screenDisplayMetrics)
} catch (_: Exception) {
// Non-visual contexts (e.g. Application) may throw on API 30+.
// Falls back to resource display metrics copied via setTo() above.
}
// Preserve fontScale from the configuration because getRealMetrics() returns
// physical display metrics without the system font scale setting.
// This is needed for proper text scaling when fontScale < 1.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@

package com.facebook.react.uimanager

import android.annotation.TargetApi
import android.app.Activity
import android.content.Context
import android.util.DisplayMetrics
import android.view.View
import android.view.Window
import android.view.WindowInsets
import androidx.annotation.RequiresApi
import com.facebook.react.bridge.WritableMap
import com.facebook.testutils.shadows.ShadowNativeLoader
import com.facebook.testutils.shadows.ShadowNativeMap
Expand Down Expand Up @@ -133,7 +133,7 @@ class DisplayMetricsHolderTest {
}

@Test
@TargetApi(30)
@RequiresApi(30)
fun getEncodedScreenSizeWithoutVerticalInsets_returnsEncodedValue() {
DisplayMetricsHolder.initDisplayMetrics(context)

Expand Down Expand Up @@ -183,4 +183,28 @@ class DisplayMetricsHolderTest {

assertThat(screenMetrics.scaledDensity).isEqualTo(customScaledDensity)
}

@Test
fun initDisplayMetrics_doesNotCrashWithNonVisualContext() {
val mockContext: Context = mock()
val mockResources: android.content.res.Resources = mock()
val metrics = DisplayMetrics()
metrics.density = 2.0f
metrics.scaledDensity = 2.0f
metrics.widthPixels = 1080
metrics.heightPixels = 1920
metrics.densityDpi = DisplayMetrics.DENSITY_XHIGH

whenever(mockContext.resources).thenReturn(mockResources)
whenever(mockResources.displayMetrics).thenReturn(metrics)
whenever(mockContext.getSystemService(Context.WINDOW_SERVICE))
.thenThrow(IllegalStateException("non-visual context"))

// Should not throw
DisplayMetricsHolder.initDisplayMetrics(mockContext)

// Metrics should still be set from resource display metrics
assertThat(DisplayMetricsHolder.getWindowDisplayMetrics()).isNotNull()
assertThat(DisplayMetricsHolder.getScreenDisplayMetrics()).isNotNull()
}
}
Loading