@@ -841,7 +841,7 @@ private static synchronized int getDpi() {
841841 if (sDensityDpiOverride != 0 ) {
842842 return sDensityDpiOverride ;
843843 }
844- return sScreenCompat .getDensityDpi ();
844+ return sScreenCompat .getDensityDpi (sDisplayId );
845845 }
846846
847847 public static synchronized void setDisplayDensityOverride (@ Nullable final Float density ) {
@@ -861,7 +861,7 @@ private static synchronized float getDensity() {
861861 return sDensityOverride ;
862862 }
863863
864- return sScreenCompat .getDensity ();
864+ return sScreenCompat .getDensity (sDisplayId );
865865 }
866866
867867 private static int sTotalRam ;
@@ -900,9 +900,7 @@ public static synchronized int getScreenDepth() {
900900 sScreenDepth = 16 ;
901901 final Context applicationContext = getApplicationContext ();
902902 final PixelFormat info = new PixelFormat ();
903- final WindowManager wm =
904- (WindowManager ) applicationContext .getSystemService (Context .WINDOW_SERVICE );
905- PixelFormat .getPixelFormatInfo (wm .getDefaultDisplay ().getPixelFormat (), info );
903+ PixelFormat .getPixelFormatInfo (sScreenCompat .getDisplay (sDisplayId ).getPixelFormat (), info );
906904 if (info .bitsPerPixel >= 24 && isHighMemoryDevice (applicationContext )) {
907905 sScreenDepth = sUseMaxScreenDepth ? info .bitsPerPixel : 24 ;
908906 }
@@ -912,14 +910,12 @@ public static synchronized int getScreenDepth() {
912910 }
913911
914912 @ WrapForJNI (calledFrom = "gecko" )
915- public static synchronized float getScreenRefreshRate () {
913+ private static synchronized float getScreenRefreshRate () {
916914 if (sScreenRefreshRate != null ) {
917915 return sScreenRefreshRate ;
918916 }
919917
920- final WindowManager wm =
921- (WindowManager ) getApplicationContext ().getSystemService (Context .WINDOW_SERVICE );
922- final float refreshRate = wm .getDefaultDisplay ().getRefreshRate ();
918+ final float refreshRate = sScreenCompat .getDisplay (sDisplayId ).getRefreshRate ();
923919 // Android 11+ supports multiple refresh rate. So we have to get refresh rate per call.
924920 // https://source.android.com/docs/core/graphics/multiple-refresh-rate
925921 if (Build .VERSION .SDK_INT < 30 ) {
@@ -931,9 +927,7 @@ public static synchronized float getScreenRefreshRate() {
931927
932928 @ WrapForJNI (calledFrom = "gecko" )
933929 private static boolean hasHDRScreen () {
934- final Display display =
935- ((DisplayManager ) getApplicationContext ().getSystemService (Context .DISPLAY_SERVICE ))
936- .getDisplay (Display .DEFAULT_DISPLAY );
930+ final Display display = sScreenCompat .getDisplay (sDisplayId );
937931 return display != null && display .isHdr ();
938932 }
939933
@@ -1307,7 +1301,7 @@ private static short getScreenOrientation() {
13071301 }
13081302
13091303 /* package */ static int getRotation () {
1310- return sScreenCompat .getRotation ();
1304+ return sScreenCompat .getRotation (sDisplayId );
13111305 }
13121306
13131307 @ WrapForJNI (calledFrom = "gecko" )
@@ -1486,13 +1480,17 @@ public static synchronized void setScreenSizeOverride(final Rect size) {
14861480 static final ScreenCompat sScreenCompat ;
14871481
14881482 private interface ScreenCompat {
1489- Rect getScreenSize ();
1483+ Rect getScreenSize (int displayId );
14901484
1491- int getRotation ();
1485+ int getRotation (int displayId );
14921486
1493- int getDensityDpi ();
1487+ int getDensityDpi (int displayId );
14941488
1495- float getDensity ();
1489+ float getDensity (int displayId );
1490+
1491+ Display getDisplay (int displayId );
1492+
1493+ void onDisplayRemoved (int displayId );
14961494 }
14971495
14981496 private static class JellyBeanMR1ScreenCompat implements ScreenCompat {
@@ -1504,94 +1502,143 @@ private static DisplayMetrics getDisplayMetrics() {
15041502 }
15051503
15061504 @ Override
1507- public Rect getScreenSize () {
1508- final WindowManager wm =
1509- (WindowManager ) getApplicationContext ().getSystemService (Context .WINDOW_SERVICE );
1510- final Display disp = wm .getDefaultDisplay ();
1505+ public Rect getScreenSize (final int displayId ) {
1506+ final Display disp = getDisplay (displayId );
15111507 final Point size = new Point ();
15121508 disp .getRealSize (size );
15131509 return new Rect (0 , 0 , size .x , size .y );
15141510 }
15151511
15161512 @ Override
1517- public int getRotation () {
1518- final WindowManager wm =
1519- (WindowManager ) getApplicationContext ().getSystemService (Context .WINDOW_SERVICE );
1520- return wm .getDefaultDisplay ().getRotation ();
1513+ public int getRotation (final int displayId ) {
1514+ return getDisplay (displayId ).getRotation ();
15211515 }
15221516
15231517 @ Override
1524- public int getDensityDpi () {
1518+ public int getDensityDpi (final int displayId ) {
15251519 if (mDensityDpi == 0 ) {
15261520 mDensityDpi = getDisplayMetrics ().densityDpi ;
15271521 }
15281522 return mDensityDpi ;
15291523 }
15301524
15311525 @ Override
1532- public float getDensity () {
1526+ public float getDensity (final int displayId ) {
15331527 if (mDensity == null ) {
15341528 mDensity = getDisplayMetrics ().density ;
15351529 }
15361530 return mDensity ;
15371531 }
1532+
1533+ @ Override
1534+ public Display getDisplay (final int displayId ) {
1535+ final DisplayManager displayManager =
1536+ (DisplayManager ) getApplicationContext ().getSystemService (Context .DISPLAY_SERVICE );
1537+ final Display display = displayManager .getDisplay (displayId );
1538+ if (display != null ) {
1539+ return display ;
1540+ }
1541+ if (displayId != Display .DEFAULT_DISPLAY ) {
1542+ return getDisplay (Display .DEFAULT_DISPLAY );
1543+ }
1544+ // No display found even if default display. This should not happen.
1545+ throw new RuntimeException ("No default display found" );
1546+ }
1547+
1548+ @ Override
1549+ public void onDisplayRemoved (final int displayId ) {}
15381550 }
15391551
15401552 @ RequiresApi (Build .VERSION_CODES .S )
15411553 private static class AndroidSScreenCompat implements ScreenCompat {
15421554 @ SuppressLint ("StaticFieldLeak" )
1543- private static Context sWindowContext ;
1544-
1545- private static Context getWindowContext () {
1546- if (sWindowContext == null ) {
1547- final DisplayManager displayManager =
1548- (DisplayManager ) getApplicationContext ().getSystemService (Context .DISPLAY_SERVICE );
1549- final Display display = displayManager .getDisplay (Display .DEFAULT_DISPLAY );
1550- sWindowContext =
1551- getApplicationContext ()
1552- .createWindowContext (display , WindowManager .LayoutParams .TYPE_APPLICATION , null );
1553- sWindowContext .registerComponentCallbacks (
1554- new ComponentCallbacks () {
1555- @ Override
1556- public void onConfigurationChanged (final Configuration newConfig ) {
1557- if (GeckoScreenOrientation .getInstance ().update ()) {
1558- // refreshScreenInfo is already called.
1559- return ;
1560- }
1561- ScreenManagerHelper .refreshScreenInfo ();
1562- }
1563-
1564- @ Override
1565- public void onLowMemory () {}
1566- });
1555+ private final SimpleArrayMap <Integer , Context > mWindowContextMap = new SimpleArrayMap <>();
1556+
1557+ private final ComponentCallbacks mComponentCallbacks =
1558+ new ComponentCallbacks () {
1559+ @ Override
1560+ public void onConfigurationChanged (final Configuration newConfig ) {
1561+ if (GeckoScreenOrientation .getInstance ().update ()) {
1562+ // refreshScreenInfo is already called.
1563+ return ;
1564+ }
1565+ ScreenManagerHelper .refreshScreenInfo ();
1566+ }
1567+
1568+ @ Override
1569+ public void onLowMemory () {}
1570+ };
1571+
1572+ private synchronized Context getWindowContext (final int displayId ) {
1573+ Context windowContext = mWindowContextMap .get (displayId );
1574+ if (windowContext != null ) {
1575+ return windowContext ;
15671576 }
1568- return sWindowContext ;
1577+
1578+ final DisplayManager displayManager =
1579+ (DisplayManager ) getApplicationContext ().getSystemService (Context .DISPLAY_SERVICE );
1580+ final Display display = displayManager .getDisplay (displayId );
1581+ if (display == null ) {
1582+ if (displayId != Display .DEFAULT_DISPLAY ) {
1583+ return getWindowContext (Display .DEFAULT_DISPLAY );
1584+ }
1585+ // No display found even if default display. This should not happen.
1586+ throw new RuntimeException ("No default display found" );
1587+ }
1588+ windowContext =
1589+ getApplicationContext ()
1590+ .createWindowContext (display , WindowManager .LayoutParams .TYPE_APPLICATION , null );
1591+ windowContext .registerComponentCallbacks (mComponentCallbacks );
1592+ mWindowContextMap .put (displayId , windowContext );
1593+
1594+ return windowContext ;
15691595 }
15701596
1571- private static DisplayMetrics getDisplayMetrics () {
1572- return getWindowContext ().getResources ().getDisplayMetrics ();
1597+ private DisplayMetrics getDisplayMetrics (final int displayId ) {
1598+ return getWindowContext (displayId ).getResources ().getDisplayMetrics ();
15731599 }
15741600
15751601 @ Override
1576- public Rect getScreenSize () {
1577- final WindowManager windowManager = getWindowContext ().getSystemService (WindowManager .class );
1602+ public Rect getScreenSize (final int displayId ) {
1603+ final WindowManager windowManager =
1604+ getWindowContext (displayId ).getSystemService (WindowManager .class );
15781605 return windowManager .getCurrentWindowMetrics ().getBounds ();
15791606 }
15801607
15811608 @ Override
1582- public int getRotation () {
1583- final WindowManager windowManager = getWindowContext ().getSystemService (WindowManager .class );
1584- return windowManager .getDefaultDisplay ().getRotation ();
1609+ public int getRotation (final int displayId ) {
1610+ return getDisplay (displayId ).getRotation ();
1611+ }
1612+
1613+ @ Override
1614+ public int getDensityDpi (final int displayId ) {
1615+ return getDisplayMetrics (displayId ).densityDpi ;
1616+ }
1617+
1618+ @ Override
1619+ public float getDensity (final int displayId ) {
1620+ return getDisplayMetrics (displayId ).density ;
15851621 }
15861622
15871623 @ Override
1588- public int getDensityDpi () {
1589- return getDisplayMetrics ().densityDpi ;
1624+ public Display getDisplay (final int displayId ) {
1625+ final Display display = getWindowContext (displayId ).getDisplay ();
1626+ if (display != null ) {
1627+ return display ;
1628+ }
1629+ if (displayId != Display .DEFAULT_DISPLAY ) {
1630+ return getWindowContext (Display .DEFAULT_DISPLAY ).getDisplay ();
1631+ }
1632+ // No display found even if default display. This should not happen.
1633+ throw new RuntimeException ("No default display found" );
15901634 }
15911635
15921636 @ Override
1593- public float getDensity () {
1594- return getDisplayMetrics ().density ;
1637+ public synchronized void onDisplayRemoved (final int displayId ) {
1638+ final Context context = mWindowContextMap .remove (displayId );
1639+ if (context != null ) {
1640+ context .unregisterComponentCallbacks (mComponentCallbacks );
1641+ }
15951642 }
15961643 }
15971644
@@ -1603,8 +1650,11 @@ public float getDensity() {
16031650 }
16041651 }
16051652
1653+ /** The display id that is associated with the GeckoView object. */
1654+ private static volatile int sDisplayId = Display .DEFAULT_DISPLAY ;
1655+
16061656 /* package */ static Rect getScreenSizeIgnoreOverride () {
1607- return sScreenCompat .getScreenSize ();
1657+ return sScreenCompat .getScreenSize (sDisplayId );
16081658 }
16091659
16101660 @ WrapForJNI (calledFrom = "gecko" )
@@ -1616,6 +1666,23 @@ private static synchronized Rect getScreenSize() {
16161666 return getScreenSizeIgnoreOverride ();
16171667 }
16181668
1669+ /* package */ static void onDisplayRemoved (final int displayId ) {
1670+ sScreenCompat .onDisplayRemoved (displayId );
1671+ }
1672+
1673+ /* package */ static int getDisplayId () {
1674+ return sDisplayId ;
1675+ }
1676+
1677+ /**
1678+ * Set the display id that is associated with the GeckoView object.
1679+ *
1680+ * @param displayId The display id.
1681+ */
1682+ public static void setDisplayId (final int displayId ) {
1683+ sDisplayId = displayId ;
1684+ }
1685+
16191686 @ WrapForJNI (calledFrom = "any" )
16201687 public static int getAudioOutputFramesPerBuffer () {
16211688 if (BuildConfig .DEBUG_BUILD && isIsolatedProcess ()) {
0 commit comments