Bug 1475875 - Use ScreenManager on Android r=esawin,jchen draft
authorJames Willcox <snorp@snorp.net>
Fri, 27 Jul 2018 13:24:49 -0500
changeset 826470 fdadf22d5e28423fe442cee7e9e5d9c22f98cf1f
parent 826469 1e9ecba54e7b1e6ee614e323ece9c98c373311a9
push id118333
push userbmo:snorp@snorp.net
push dateFri, 03 Aug 2018 20:42:37 +0000
reviewersesawin, jchen
bugs1475875
milestone63.0a1
Bug 1475875 - Use ScreenManager on Android r=esawin,jchen This ensures we have screen information with e10s. MozReview-Commit-ID: 1zghxZuLqr3
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/ScreenHelperAndroid.cpp
widget/android/ScreenHelperAndroid.h
widget/android/moz.build
widget/android/nsAppShell.cpp
widget/android/nsScreenManagerAndroid.cpp
widget/android/nsScreenManagerAndroid.h
widget/android/nsWidgetFactory.cpp
widget/android/nsWindow.cpp
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -318,33 +318,16 @@ AndroidBridge::GetClipboardText(nsAStrin
 
     if (text) {
         aText = text->ToString();
     }
     return !!text;
 }
 
 int
-AndroidBridge::GetDPI()
-{
-    static int sDPI = 0;
-    if (sDPI)
-        return sDPI;
-
-    const int DEFAULT_DPI = 160;
-
-    sDPI = GeckoAppShell::GetDpi();
-    if (!sDPI) {
-        return DEFAULT_DPI;
-    }
-
-    return sDPI;
-}
-
-int
 AndroidBridge::GetScreenDepth()
 {
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     static int sDepth = 0;
     if (sDepth)
         return sDepth;
 
@@ -353,16 +336,17 @@ AndroidBridge::GetScreenDepth()
     if (jni::IsAvailable()) {
         sDepth = GeckoAppShell::GetScreenDepth();
     }
     if (!sDepth)
         return DEFAULT_DEPTH;
 
     return sDepth;
 }
+
 void
 AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
 {
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     uint32_t len = aPattern.Length();
     if (!len) {
         ALOG_BRIDGE("  invalid 0-length array");
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -111,17 +111,16 @@ public:
     bool GetHWEncoderCapability();
     bool GetHWDecoderCapability();
 
     void GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType);
     void GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt);
 
     bool GetClipboardText(nsAString& aText);
 
-    int GetDPI();
     int GetScreenDepth();
 
     void Vibrate(const nsTArray<uint32_t>& aPattern);
 
     void GetSystemColors(AndroidSystemColors *aColors);
 
     void GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, uint8_t * const aBuf);
 
new file mode 100644
--- /dev/null
+++ b/widget/android/ScreenHelperAndroid.cpp
@@ -0,0 +1,146 @@
+/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set sw=4 ts=4 expandtab:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "ScreenHelperAndroid.h"
+#include "AndroidRect.h"
+#include "GeneratedJNINatives.h"
+#include "nsThreadUtils.h"
+
+#include <mozilla/jni/Refs.h>
+
+#include "mozilla/Atomics.h"
+#include "mozilla/widget/ScreenManager.h"
+
+using namespace mozilla;
+using namespace mozilla::java;
+using namespace mozilla::widget;
+
+static ScreenHelperAndroid* gHelper = nullptr;
+
+class ScreenHelperAndroid::ScreenHelperSupport final
+    : public ScreenManagerHelper::Natives<ScreenHelperSupport>
+{
+public:
+    typedef ScreenManagerHelper::Natives<ScreenHelperSupport> Base;
+
+    static int32_t AddDisplay(int32_t aDisplayType, int32_t aWidth, int32_t aHeight, float aDensity) {
+        static Atomic<uint32_t> nextId;
+
+        uint32_t screenId = ++nextId;
+        NS_DispatchToMainThread(NS_NewRunnableFunction(
+            "ScreenHelperAndroid::ScreenHelperSupport::AddDisplay",
+            [aDisplayType, aWidth, aHeight, aDensity, screenId] {
+                MOZ_ASSERT(NS_IsMainThread());
+
+                gHelper->AddScreen(screenId,
+                                   static_cast<DisplayType>(aDisplayType),
+                                   LayoutDeviceIntRect(0, 0, aWidth, aHeight),
+                                   aDensity);
+            }).take());
+        return screenId;
+    }
+
+    static void RemoveDisplay(int32_t aScreenId) {
+        NS_DispatchToMainThread(NS_NewRunnableFunction(
+            "ScreenHelperAndroid::ScreenHelperSupport::RemoveDisplay",
+            [aScreenId] {
+                MOZ_ASSERT(NS_IsMainThread());
+
+                gHelper->RemoveScreen(aScreenId);
+            }).take());
+    }
+};
+
+static already_AddRefed<Screen>
+MakePrimaryScreen() {
+    MOZ_ASSERT(XRE_IsParentProcess());
+    if (!jni::IsAvailable()) {
+        return nullptr;
+    }
+
+    java::sdk::Rect::LocalRef rect = GeckoAppShell::GetScreenSize();
+    LayoutDeviceIntRect bounds = LayoutDeviceIntRect(rect->Left(), rect->Top(),
+                                                     rect->Width(), rect->Height());
+    uint32_t depth = GeckoAppShell::GetScreenDepth();
+    float density = GeckoAppShell::GetDensity();
+    float dpi = GeckoAppShell::GetDpi();
+    RefPtr<Screen> screen = new Screen(bounds, bounds, depth, depth,
+                                       DesktopToLayoutDeviceScale(density),
+                                       CSSToLayoutDeviceScale(1.0f),
+                                       dpi);
+    return screen.forget();
+}
+
+ScreenHelperAndroid::ScreenHelperAndroid()
+{
+    MOZ_ASSERT(!gHelper);
+    gHelper = this;
+
+    ScreenHelperSupport::Base::Init();
+
+    Refresh();
+}
+
+ScreenHelperAndroid::~ScreenHelperAndroid()
+{
+    gHelper = nullptr;
+}
+
+/* static */ ScreenHelperAndroid*
+ScreenHelperAndroid::GetSingleton()
+{
+    return gHelper;
+}
+
+void
+ScreenHelperAndroid::Refresh() {
+    mScreens.Remove(0);
+
+    AutoTArray<RefPtr<Screen>, 1> screenList;
+    RefPtr<Screen> screen = MakePrimaryScreen();
+    if (screen) {
+        mScreens.Put(0, screen);
+    }
+
+    for (auto iter = mScreens.ConstIter(); !iter.Done(); iter.Next()) {
+        screenList.AppendElement(iter.Data());
+    }
+
+    ScreenManager& manager = ScreenManager::GetSingleton();
+    manager.Refresh(std::move(screenList));
+}
+
+void
+ScreenHelperAndroid::AddScreen(uint32_t aScreenId,
+                               DisplayType aDisplayType,
+                               LayoutDeviceIntRect aRect,
+                               float aDensity)
+{
+    MOZ_ASSERT(aScreenId > 0);
+    MOZ_ASSERT(!mScreens.Get(aScreenId, nullptr));
+
+    RefPtr<Screen> screen = new Screen(aRect, aRect, 24, 24,
+                                       DesktopToLayoutDeviceScale(aDensity),
+                                       CSSToLayoutDeviceScale(1.0f),
+                                       160.0f);
+
+    mScreens.Put(aScreenId, screen);
+    Refresh();
+}
+
+void
+ScreenHelperAndroid::RemoveScreen(uint32_t aScreenId)
+{
+    mScreens.Remove(aScreenId);
+    Refresh();
+}
+
+already_AddRefed<Screen>
+ScreenHelperAndroid::ScreenForId(uint32_t aScreenId)
+{
+    RefPtr<Screen> screen = mScreens.Get(aScreenId);
+    return screen.forget();
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/widget/android/ScreenHelperAndroid.h
@@ -0,0 +1,43 @@
+/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: ts=4 sw=4 expandtab:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef ScreenHelperAndroid_h___
+#define ScreenHelperAndroid_h___
+
+#include "mozilla/widget/ScreenManager.h"
+#include "nsDataHashtable.h"
+
+namespace mozilla {
+namespace widget {
+
+class ScreenHelperAndroid final : public ScreenManager::Helper
+{
+public:
+    class ScreenHelperSupport;
+
+    ScreenHelperAndroid();
+    ~ScreenHelperAndroid();
+
+    static ScreenHelperAndroid* GetSingleton();
+
+    void Refresh();
+
+    void AddScreen(uint32_t aScreenId,
+                   DisplayType aDisplayType,
+                   LayoutDeviceIntRect aRect = LayoutDeviceIntRect(),
+                   float aDensity = 1.0f);
+    void RemoveScreen(uint32_t aId);
+    already_AddRefed<Screen> ScreenForId(uint32_t aScreenId);
+
+private:
+    nsDataHashtable<nsUint32HashKey, RefPtr<Screen>> mScreens;
+};
+
+} // widget
+} // mozilla
+
+#endif /* ScreenHelperAndroid_h___ */
+
--- a/widget/android/moz.build
+++ b/widget/android/moz.build
@@ -53,19 +53,19 @@ UNIFIED_SOURCES += [
     'nsAndroidProtocolHandler.cpp',
     'nsAppShell.cpp',
     'nsClipboard.cpp',
     'nsDeviceContextAndroid.cpp',
     'nsIdleServiceAndroid.cpp',
     'nsLookAndFeel.cpp',
     'nsNativeThemeAndroid.cpp',
     'nsPrintSettingsServiceAndroid.cpp',
-    'nsScreenManagerAndroid.cpp',
     'nsWidgetFactory.cpp',
     'nsWindow.cpp',
+    'ScreenHelperAndroid.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 # The recursive make backend treats the first output specially: it's passed as
 # an open FileAvoidWrite to the invoked script.  That doesn't work well with
 # the Gradle task that generates all of the outputs, so we add a dummy first
 # output.
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -31,16 +31,17 @@
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Hal.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/intl/OSPreferences.h"
+#include "mozilla/widget/ScreenManager.h"
 #include "prenv.h"
 
 #include "AndroidBridge.h"
 #include "AndroidBridgeUtilities.h"
 #include "GeneratedJNINatives.h"
 #include <android/log.h>
 #include <pthread.h>
 #include <wchar.h>
@@ -63,24 +64,26 @@
 #include "GeckoNetworkManager.h"
 #include "GeckoProcessManager.h"
 #include "GeckoScreenOrientation.h"
 #include "GeckoVRManager.h"
 #include "PrefsHelper.h"
 #include "fennec/MemoryMonitor.h"
 #include "fennec/Telemetry.h"
 #include "fennec/ThumbnailHelper.h"
+#include "ScreenHelperAndroid.h"
 
 #ifdef DEBUG_ANDROID_EVENTS
 #define EVLOG(args...)  ALOG(args)
 #else
 #define EVLOG(args...) do { } while (0)
 #endif
 
 using namespace mozilla;
+using namespace mozilla::widget;
 
 nsIGeolocationUpdate *gLocationCallback = nullptr;
 
 nsAppShell* nsAppShell::sAppShell;
 StaticAutoPtr<Mutex> nsAppShell::sAppShellLock;
 
 uint32_t nsAppShell::Queue::sLatencyCount[];
 uint64_t nsAppShell::Queue::sLatencyTime[];
@@ -408,16 +411,20 @@ nsAppShell::nsAppShell()
             GeckoAppShellSupport::Init();
 
             // Set the corresponding state in GeckoThread.
             java::GeckoThread::SetState(java::GeckoThread::State::RUNNING());
         }
         return;
     }
 
+
+    ScreenManager& screenManager = ScreenManager::GetSingleton();
+    screenManager.SetHelper(mozilla::MakeUnique<ScreenHelperAndroid>());
+
     if (jni::IsAvailable()) {
         // Initialize JNI and Set the corresponding state in GeckoThread.
         AndroidBridge::ConstructBridge();
         GeckoAppShellSupport::Init();
         GeckoThreadSupport::Init();
         mozilla::GeckoBatteryManager::Init();
         mozilla::GeckoNetworkManager::Init();
         mozilla::GeckoProcessManager::Init();
deleted file mode 100644
--- a/widget/android/nsScreenManagerAndroid.cpp
+++ /dev/null
@@ -1,228 +0,0 @@
-/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set sw=4 ts=4 expandtab:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#define MOZ_FATAL_ASSERTIONS_FOR_THREAD_SAFETY
-
-#include "mozilla/SyncRunnable.h"
-#include "nsScreenManagerAndroid.h"
-#include "nsServiceManagerUtils.h"
-#include "AndroidRect.h"
-#include "GeneratedJNINatives.h"
-#include "nsAppShell.h"
-#include "nsThreadUtils.h"
-
-#include <android/log.h>
-#include <mozilla/jni/Refs.h>
-
-#define ALOG(args...) __android_log_print(ANDROID_LOG_INFO, "nsScreenManagerAndroid", ## args)
-
-using namespace mozilla;
-using namespace mozilla::java;
-
-static uint32_t sScreenId = 0;
-const uint32_t PRIMARY_SCREEN_ID = 0;
-
-nsScreenAndroid::nsScreenAndroid(DisplayType aDisplayType, nsIntRect aRect)
-    : mId(sScreenId++)
-    , mDisplayType(aDisplayType)
-    , mRect(aRect)
-    , mDensity(0.0)
-{
-    // ensure that the ID of the primary screen would be PRIMARY_SCREEN_ID.
-    if (mDisplayType == DisplayType::DISPLAY_PRIMARY) {
-        mId = PRIMARY_SCREEN_ID;
-    }
-}
-
-nsScreenAndroid::~nsScreenAndroid()
-{
-}
-
-float
-nsScreenAndroid::GetDensity() {
-    if (mDensity != 0.0) {
-        return mDensity;
-    }
-    if (mDisplayType == DisplayType::DISPLAY_PRIMARY) {
-        mDensity = mozilla::jni::IsAvailable() ? GeckoAppShell::GetDensity()
-                                               : 1.0; // xpcshell most likely
-        return mDensity;
-    }
-    return 1.0;
-}
-
-NS_IMETHODIMP
-nsScreenAndroid::GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
-{
-    if (mDisplayType != DisplayType::DISPLAY_PRIMARY) {
-        *outLeft   = mRect.x;
-        *outTop    = mRect.y;
-        *outWidth  = mRect.width;
-        *outHeight = mRect.height;
-
-        return NS_OK;
-    }
-
-    if (!mozilla::jni::IsAvailable()) {
-      // xpcshell most likely
-      *outLeft = *outTop = *outWidth = *outHeight = 0;
-      return NS_ERROR_FAILURE;
-    }
-
-    java::sdk::Rect::LocalRef rect = java::GeckoAppShell::GetScreenSize();
-    *outLeft = rect->Left();
-    *outTop = rect->Top();
-    *outWidth = rect->Width();
-    *outHeight = rect->Height();
-
-    return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsScreenAndroid::GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
-{
-    return GetRect(outLeft, outTop, outWidth, outHeight);
-}
-
-
-
-NS_IMETHODIMP
-nsScreenAndroid::GetPixelDepth(int32_t *aPixelDepth)
-{
-    if (!mozilla::jni::IsAvailable()) {
-      // xpcshell most likely
-      *aPixelDepth = 16;
-      return NS_ERROR_FAILURE;
-    }
-
-    *aPixelDepth = java::GeckoAppShell::GetScreenDepth();
-    return NS_OK;
-}
-
-
-NS_IMETHODIMP
-nsScreenAndroid::GetColorDepth(int32_t *aColorDepth)
-{
-    return GetPixelDepth(aColorDepth);
-}
-
-class nsScreenManagerAndroid::ScreenManagerHelperSupport final
-    : public ScreenManagerHelper::Natives<ScreenManagerHelperSupport>
-{
-public:
-    typedef ScreenManagerHelper::Natives<ScreenManagerHelperSupport> Base;
-
-    static int32_t AddDisplay(int32_t aDisplayType, int32_t aWidth, int32_t aHeight, float aDensity) {
-        int32_t screenId = -1; // return value
-        nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
-        SyncRunnable::DispatchToThread(mainThread, NS_NewRunnableFunction(
-            "nsScreenManagerAndroid::ScreenManagerHelperSupport::AddDisplay",
-            [&aDisplayType, &aWidth, &aHeight, &aDensity, &screenId] {
-                MOZ_ASSERT(NS_IsMainThread());
-                nsCOMPtr<nsIScreenManager> screenMgr =
-                do_GetService("@mozilla.org/gfx/screenmanager;1");
-                MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
-
-                RefPtr<nsScreenManagerAndroid> screenMgrAndroid =
-                (nsScreenManagerAndroid*) screenMgr.get();
-                RefPtr<nsScreenAndroid> screen =
-                screenMgrAndroid->AddScreen(static_cast<DisplayType>(aDisplayType),
-                                            nsIntRect(0, 0, aWidth, aHeight));
-                MOZ_ASSERT(screen);
-                screen->SetDensity(aDensity);
-                screenId = static_cast<int32_t>(screen->GetId());
-            }).take());
-        return screenId;
-    }
-
-    static void RemoveDisplay(int32_t aScreenId) {
-        nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
-        SyncRunnable::DispatchToThread(mainThread, NS_NewRunnableFunction(
-            "nsScreenManagerAndroid::ScreenManagerHelperSupport::RemoveDisplay",
-            [&aScreenId] {
-                MOZ_ASSERT(NS_IsMainThread());
-                nsCOMPtr<nsIScreenManager> screenMgr =
-                    do_GetService("@mozilla.org/gfx/screenmanager;1");
-                MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
-
-                RefPtr<nsScreenManagerAndroid> screenMgrAndroid =
-                    (nsScreenManagerAndroid*) screenMgr.get();
-                screenMgrAndroid->RemoveScreen(aScreenId);
-            }).take());
-    }
-};
-
-NS_IMPL_ISUPPORTS(nsScreenManagerAndroid, nsIScreenManager)
-
-nsScreenManagerAndroid::nsScreenManagerAndroid()
-{
-    if (mozilla::jni::IsAvailable()) {
-        ScreenManagerHelperSupport::Base::Init();
-    }
-    nsCOMPtr<nsIScreen> screen = AddScreen(DisplayType::DISPLAY_PRIMARY);
-    MOZ_ASSERT(screen);
-}
-
-nsScreenManagerAndroid::~nsScreenManagerAndroid()
-{
-}
-
-NS_IMETHODIMP
-nsScreenManagerAndroid::GetPrimaryScreen(nsIScreen **outScreen)
-{
-    RefPtr<nsScreenAndroid> screen = ScreenForId(PRIMARY_SCREEN_ID);
-    if (screen) {
-        screen.forget(outScreen);
-    }
-    return NS_OK;
-}
-
-already_AddRefed<nsScreenAndroid>
-nsScreenManagerAndroid::ScreenForId(uint32_t aId)
-{
-    for (size_t i = 0; i < mScreens.Length(); ++i) {
-        if (aId == mScreens[i]->GetId()) {
-            RefPtr<nsScreenAndroid> screen = mScreens[i];
-            return screen.forget();
-        }
-    }
-
-    return nullptr;
-}
-
-NS_IMETHODIMP
-nsScreenManagerAndroid::ScreenForRect(int32_t inLeft,
-                                      int32_t inTop,
-                                      int32_t inWidth,
-                                      int32_t inHeight,
-                                      nsIScreen **outScreen)
-{
-    // Not support to query non-primary screen with rect.
-    return GetPrimaryScreen(outScreen);
-}
-
-already_AddRefed<nsScreenAndroid>
-nsScreenManagerAndroid::AddScreen(DisplayType aDisplayType, nsIntRect aRect)
-{
-    ALOG("nsScreenManagerAndroid: add %s screen",
-        (aDisplayType == DisplayType::DISPLAY_PRIMARY  ? "PRIMARY"  :
-        (aDisplayType == DisplayType::DISPLAY_EXTERNAL ? "EXTERNAL" :
-                                                         "VIRTUAL")));
-    RefPtr<nsScreenAndroid> screen = new nsScreenAndroid(aDisplayType, aRect);
-    mScreens.AppendElement(screen);
-    return screen.forget();
-}
-
-void
-nsScreenManagerAndroid::RemoveScreen(uint32_t aScreenId)
-{
-    for (size_t i = 0; i < mScreens.Length(); i++) {
-        if (aScreenId == mScreens[i]->GetId()) {
-            mScreens.RemoveElementAt(i);
-        }
-    }
-}
deleted file mode 100644
--- a/widget/android/nsScreenManagerAndroid.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: ts=4 sw=4 expandtab:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsScreenManagerAndroid_h___
-#define nsScreenManagerAndroid_h___
-
-#include "nsCOMPtr.h"
-
-#include "nsBaseScreen.h"
-#include "nsIScreenManager.h"
-#include "nsRect.h"
-#include "mozilla/WidgetUtils.h"
-
-class nsScreenAndroid final : public nsBaseScreen
-{
-public:
-    nsScreenAndroid(DisplayType aDisplayType, nsIntRect aRect);
-    ~nsScreenAndroid();
-
-    NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
-    NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop, int32_t* aWidth, int32_t* aHeight) override;
-    NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override;
-    NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override;
-
-    uint32_t GetId() const { return mId; };
-    DisplayType GetDisplayType() const { return mDisplayType; }
-
-    void SetDensity(double aDensity) { mDensity = aDensity; }
-    float GetDensity();
-
-private:
-    uint32_t mId;
-    DisplayType mDisplayType;
-    nsIntRect mRect;
-    float mDensity;
-};
-
-class nsScreenManagerAndroid final : public nsIScreenManager
-{
-private:
-    ~nsScreenManagerAndroid();
-
-public:
-    class ScreenManagerHelperSupport;
-
-    nsScreenManagerAndroid();
-
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSISCREENMANAGER
-
-    already_AddRefed<nsScreenAndroid> ScreenForId(uint32_t aId);
-    already_AddRefed<nsScreenAndroid> AddScreen(DisplayType aDisplayType,
-                                                nsIntRect aRect = nsIntRect());
-    void RemoveScreen(uint32_t aScreenId);
-
-protected:
-    nsTArray<RefPtr<nsScreenAndroid>> mScreens;
-};
-
-#endif /* nsScreenManagerAndroid_h___ */
--- a/widget/android/nsWidgetFactory.cpp
+++ b/widget/android/nsWidgetFactory.cpp
@@ -9,35 +9,39 @@
 #include "nsCOMPtr.h"
 #include "nsWidgetsCID.h"
 #include "nsAppShell.h"
 #include "AndroidBridge.h"
 
 #include "nsWindow.h"
 #include "nsLookAndFeel.h"
 #include "nsAppShellSingleton.h"
-#include "nsScreenManagerAndroid.h"
 
 #include "nsIdleServiceAndroid.h"
 #include "nsClipboard.h"
 #include "nsClipboardHelper.h"
 #include "nsTransferable.h"
 #include "nsPrintSession.h"
 #include "nsPrintSettingsServiceAndroid.h"
 #include "nsDeviceContextAndroid.h"
 #include "nsHTMLFormatConverter.h"
 #include "nsXULAppAPI.h"
 #include "nsAndroidProtocolHandler.h"
 
 #include "nsToolkitCompsCID.h"
 #include "AndroidAlerts.h"
 #include "nsNativeThemeAndroid.h"
 
+#include "mozilla/widget/ScreenManager.h"
+
+using namespace mozilla;
+using namespace mozilla::widget;
+
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerAndroid)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceAndroid, nsIdleServiceAndroid::GetInstance)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSettingsServiceAndroid, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecAndroid)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
@@ -90,17 +94,18 @@ NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
 NS_DEFINE_NAMED_CID(NS_ANDROIDBRIDGE_CID);
 NS_DEFINE_NAMED_CID(NS_ANDROIDPROTOCOLHANDLER_CID);
 NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID);
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
   { &kNS_WINDOW_CID, false, nullptr, nsWindowConstructor },
   { &kNS_CHILD_CID, false, nullptr, nsWindowConstructor },
   { &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor },
-  { &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerAndroidConstructor },
+  { &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor,
+    mozilla::Module::MAIN_PROCESS_ONLY },
   { &kNS_THEMERENDERER_CID, false, nullptr, nsNativeThemeAndroidConstructor },
   { &kNS_IDLE_SERVICE_CID, false, nullptr, nsIdleServiceAndroidConstructor },
   { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor },
   { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor },
   { &kNS_CLIPBOARDHELPER_CID, false, nullptr, nsClipboardHelperConstructor },
   { &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintSettingsServiceAndroidConstructor },
   { &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor },
   { &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecAndroidConstructor },
@@ -111,17 +116,18 @@ static const mozilla::Module::CIDEntry k
   { &kNS_SYSTEMALERTSSERVICE_CID, false, nullptr, mozilla::widget::AndroidAlertsConstructor },
   { nullptr }
 };
 
 static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
   { "@mozilla.org/widgets/window/android;1", &kNS_WINDOW_CID },
   { "@mozilla.org/widgets/child_window/android;1", &kNS_CHILD_CID },
   { "@mozilla.org/widget/appshell/android;1", &kNS_APPSHELL_CID },
-  { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
+  { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID,
+    mozilla::Module::MAIN_PROCESS_ONLY },
   { "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
   { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
   { "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
   { "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID },
   { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
   { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
   { "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID },
   { "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -73,16 +73,17 @@ using mozilla::Unused;
 #include "AndroidBridge.h"
 #include "AndroidBridgeUtilities.h"
 #include "AndroidUiThread.h"
 #include "FennecJNINatives.h"
 #include "GeneratedJNINatives.h"
 #include "GeckoEditableSupport.h"
 #include "KeyEvent.h"
 #include "MotionEvent.h"
+#include "ScreenHelperAndroid.h"
 
 #include "imgIEncoder.h"
 
 #include "nsString.h"
 #include "GeckoProfiler.h" // For AUTO_PROFILER_LABEL
 #include "nsIXULRuntime.h"
 #include "nsPrintfCString.h"
 
@@ -1514,29 +1515,37 @@ nsIWidget*
 nsWindow::GetParent()
 {
     return mParent;
 }
 
 float
 nsWindow::GetDPI()
 {
-    if (AndroidBridge::Bridge())
-        return AndroidBridge::Bridge()->GetDPI();
-    return 160.0f;
+    float dpi = 160.0f;
+
+    nsCOMPtr<nsIScreen> screen = GetWidgetScreen();
+    if (screen) {
+        screen->GetDpi(&dpi);
+    }
+
+    return dpi;
 }
 
 double
 nsWindow::GetDefaultScaleInternal()
 {
+    double scale = 1.0f;
 
     nsCOMPtr<nsIScreen> screen = GetWidgetScreen();
-    MOZ_ASSERT(screen);
-    RefPtr<nsScreenAndroid> screenAndroid = (nsScreenAndroid*) screen.get();
-    return screenAndroid->GetDensity();
+    if (screen) {
+        screen->GetContentsScaleFactor(&scale);
+    }
+
+    return scale;
 }
 
 void
 nsWindow::Show(bool aState)
 {
     ALOG("nsWindow[%p]::Show %d", (void*)this, aState);
 
     if (mWindowType == eWindowType_invisible) {
@@ -2264,23 +2273,28 @@ CompositorBridgeChild*
 nsWindow::GetCompositorBridgeChild() const
 {
     return mCompositorSession ? mCompositorSession->GetCompositorBridgeChild() : nullptr;
 }
 
 already_AddRefed<nsIScreen>
 nsWindow::GetWidgetScreen()
 {
-    nsCOMPtr<nsIScreenManager> screenMgr =
-        do_GetService("@mozilla.org/gfx/screenmanager;1");
-    MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
+    nsCOMPtr<nsIScreen> screen;
+    if (mScreenId == 0) {
+        nsCOMPtr<nsIScreenManager> screenMgr =
+            do_GetService("@mozilla.org/gfx/screenmanager;1");
+        MOZ_ASSERT(screenMgr, "Failed to get nsIScreenManager");
 
-    RefPtr<nsScreenManagerAndroid> screenMgrAndroid =
-        (nsScreenManagerAndroid*) screenMgr.get();
-    return screenMgrAndroid->ScreenForId(mScreenId);
+        screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
+    } else {
+        screen = ScreenHelperAndroid::GetSingleton()->ScreenForId(mScreenId);
+    }
+
+    return screen.forget();
 }
 
 void
 nsWindow::SetContentDocumentDisplayed(bool aDisplayed)
 {
     mContentDocumentDisplayed = aDisplayed;
 }