Bug 1282003 - (Part 2) Add screenManagerHelper in Java. r?snorp draft
authorKuoE0 <kuoe0.tw@gmail.com>
Fri, 23 Sep 2016 23:03:00 +0800
changeset 426462 026d4015c91306f354318445a8fabf4c55a5e57f
parent 426461 fcd0693bc288ae7269c0158ce245fb401fdc202b
child 426463 b85488e82b8dd84bc17a861c3378c46f5f88644f
push id32690
push userbmo:kuoe0@mozilla.com
push dateTue, 18 Oct 2016 11:34:13 +0000
reviewerssnorp
bugs1282003
milestone52.0a1
Bug 1282003 - (Part 2) Add screenManagerHelper in Java. r?snorp MozReview-Commit-ID: BLw6e7dgldt
mobile/android/base/java/org/mozilla/gecko/ScreenManagerHelper.java
mobile/android/base/moz.build
widget/android/fennec/FennecJNINatives.h
widget/android/fennec/FennecJNIWrappers.cpp
widget/android/fennec/FennecJNIWrappers.h
widget/android/nsScreenManagerAndroid.cpp
widget/android/nsScreenManagerAndroid.h
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/ScreenManagerHelper.java
@@ -0,0 +1,43 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * 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/. */
+
+package org.mozilla.gecko;
+
+import org.mozilla.gecko.annotation.WrapForJNI;
+
+class ScreenManagerHelper {
+
+    /**
+     * The following display types use the same definition in nsIScreen.idl
+     */
+    final static int DISPLAY_PRIMARY  = 0; // primary screen
+    final static int DISPLAY_EXTERNAL = 1; // wired displays, such as HDMI, DisplayPort, etc.
+    final static int DISPLAY_VIRTUAL  = 2; // wireless displays, such as Chromecast, WiFi-Display, etc.
+
+    /**
+     * Add a new nsScreen when a new display in Android is available.
+     *
+     * @param displayType the display type of the nsScreen would be added
+     * @param width       the width of the new nsScreen
+     * @param height      the height of the new nsScreen
+     * @param density     the density of the new nsScreen
+     *
+     * @return            return the ID of the added nsScreen
+     */
+    @WrapForJNI
+    public native static int addDisplay(int displayType,
+                                        int width,
+                                        int height,
+                                        float density);
+
+    /**
+     * Remove the nsScreen by the specific screen ID.
+     *
+     * @param screenId    the ID of the screen would be removed.
+     */
+    @WrapForJNI
+    public native static void removeDisplay(int screenId);
+}
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -640,16 +640,17 @@ gbjar.sources += ['java/org/mozilla/geck
     'restrictions/DefaultConfiguration.java',
     'restrictions/GuestProfileConfiguration.java',
     'restrictions/Restrictable.java',
     'restrictions/RestrictedProfileConfiguration.java',
     'restrictions/RestrictionCache.java',
     'restrictions/RestrictionConfiguration.java',
     'restrictions/RestrictionProvider.java',
     'restrictions/Restrictions.java',
+    'ScreenManagerHelper.java',
     'ScreenshotObserver.java',
     'search/SearchEngine.java',
     'search/SearchEngineManager.java',
     'SessionParser.java',
     'SharedPreferencesHelper.java',
     'SiteIdentity.java',
     'SnackbarBuilder.java',
     'SuggestClient.java',
--- a/widget/android/fennec/FennecJNINatives.h
+++ b/widget/android/fennec/FennecJNINatives.h
@@ -85,16 +85,35 @@ const JNINativeMethod PresentationMediaP
             ::template Wrap<&Impl::InvalidateAndScheduleComposite>),
 
     mozilla::jni::MakeNativeMethod<PresentationMediaPlayerManager::RemovePresentationSurface_t>(
             mozilla::jni::NativeStub<PresentationMediaPlayerManager::RemovePresentationSurface_t, Impl>
             ::template Wrap<&Impl::RemovePresentationSurface>)
 };
 
 template<class Impl>
+class ScreenManagerHelper::Natives : public mozilla::jni::NativeImpl<ScreenManagerHelper, Impl>
+{
+public:
+    static const JNINativeMethod methods[2];
+};
+
+template<class Impl>
+const JNINativeMethod ScreenManagerHelper::Natives<Impl>::methods[] = {
+
+    mozilla::jni::MakeNativeMethod<ScreenManagerHelper::AddDisplay_t>(
+            mozilla::jni::NativeStub<ScreenManagerHelper::AddDisplay_t, Impl>
+            ::template Wrap<&Impl::AddDisplay>),
+
+    mozilla::jni::MakeNativeMethod<ScreenManagerHelper::RemoveDisplay_t>(
+            mozilla::jni::NativeStub<ScreenManagerHelper::RemoveDisplay_t, Impl>
+            ::template Wrap<&Impl::RemoveDisplay>)
+};
+
+template<class Impl>
 class Telemetry::Natives : public mozilla::jni::NativeImpl<Telemetry, Impl>
 {
 public:
     static const JNINativeMethod methods[5];
 };
 
 template<class Impl>
 const JNINativeMethod Telemetry::Natives<Impl>::methods[] = {
--- a/widget/android/fennec/FennecJNIWrappers.cpp
+++ b/widget/android/fennec/FennecJNIWrappers.cpp
@@ -116,16 +116,25 @@ constexpr char PresentationMediaPlayerMa
 constexpr char PresentationMediaPlayerManager::AddPresentationSurface_t::signature[];
 
 constexpr char PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t::name[];
 constexpr char PresentationMediaPlayerManager::InvalidateAndScheduleComposite_t::signature[];
 
 constexpr char PresentationMediaPlayerManager::RemovePresentationSurface_t::name[];
 constexpr char PresentationMediaPlayerManager::RemovePresentationSurface_t::signature[];
 
+const char ScreenManagerHelper::name[] =
+        "org/mozilla/gecko/ScreenManagerHelper";
+
+constexpr char ScreenManagerHelper::AddDisplay_t::name[];
+constexpr char ScreenManagerHelper::AddDisplay_t::signature[];
+
+constexpr char ScreenManagerHelper::RemoveDisplay_t::name[];
+constexpr char ScreenManagerHelper::RemoveDisplay_t::signature[];
+
 const char Telemetry::name[] =
         "org/mozilla/gecko/Telemetry";
 
 constexpr char Telemetry::AddHistogram_t::name[];
 constexpr char Telemetry::AddHistogram_t::signature[];
 
 constexpr char Telemetry::AddKeyedHistogram_t::name[];
 constexpr char Telemetry::AddKeyedHistogram_t::signature[];
--- a/widget/android/fennec/FennecJNIWrappers.h
+++ b/widget/android/fennec/FennecJNIWrappers.h
@@ -392,16 +392,68 @@ public:
     };
 
     static const mozilla::jni::CallingThread callingThread =
             mozilla::jni::CallingThread::UI;
 
     template<class Impl> class Natives;
 };
 
+class ScreenManagerHelper : public mozilla::jni::ObjectBase<ScreenManagerHelper>
+{
+public:
+    static const char name[];
+
+    explicit ScreenManagerHelper(const Context& ctx) : ObjectBase<ScreenManagerHelper>(ctx) {}
+
+    struct AddDisplay_t {
+        typedef ScreenManagerHelper Owner;
+        typedef int32_t ReturnType;
+        typedef int32_t SetterType;
+        typedef mozilla::jni::Args<
+                int32_t,
+                int32_t,
+                int32_t,
+                float> Args;
+        static constexpr char name[] = "addDisplay";
+        static constexpr char signature[] =
+                "(IIIF)I";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    struct RemoveDisplay_t {
+        typedef ScreenManagerHelper Owner;
+        typedef void ReturnType;
+        typedef void SetterType;
+        typedef mozilla::jni::Args<
+                int32_t> Args;
+        static constexpr char name[] = "removeDisplay";
+        static constexpr char signature[] =
+                "(I)V";
+        static const bool isStatic = true;
+        static const mozilla::jni::ExceptionMode exceptionMode =
+                mozilla::jni::ExceptionMode::ABORT;
+        static const mozilla::jni::CallingThread callingThread =
+                mozilla::jni::CallingThread::ANY;
+        static const mozilla::jni::DispatchTarget dispatchTarget =
+                mozilla::jni::DispatchTarget::CURRENT;
+    };
+
+    static const mozilla::jni::CallingThread callingThread =
+            mozilla::jni::CallingThread::ANY;
+
+    template<class Impl> class Natives;
+};
+
 class Telemetry : public mozilla::jni::ObjectBase<Telemetry>
 {
 public:
     static const char name[];
 
     explicit Telemetry(const Context& ctx) : ObjectBase<Telemetry>(ctx) {}
 
     struct AddHistogram_t {
--- a/widget/android/nsScreenManagerAndroid.cpp
+++ b/widget/android/nsScreenManagerAndroid.cpp
@@ -1,25 +1,31 @@
 /* -*- 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 "nsWindow.h"
-#include "GeneratedJNIWrappers.h"
+#include "nsServiceManagerUtils.h"
 #include "AndroidRect.h"
+#include "FennecJNINatives.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)
@@ -116,20 +122,67 @@ void
 nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness)
 {
     if (mDisplayType == DisplayType::DISPLAY_PRIMARY &&
         mozilla::jni::IsAvailable()) {
         java::GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
     }
 }
 
+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(
+            [&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(
+            [&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()
 {
 }
 
--- a/widget/android/nsScreenManagerAndroid.h
+++ b/widget/android/nsScreenManagerAndroid.h
@@ -43,16 +43,18 @@ private:
 };
 
 class nsScreenManagerAndroid final : public nsIScreenManager
 {
 private:
     ~nsScreenManagerAndroid();
 
 public:
+    class ScreenManagerHelperSupport;
+
     nsScreenManagerAndroid();
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSISCREENMANAGER
 
     already_AddRefed<nsScreenAndroid> AddScreen(DisplayType aDisplayType,
                                                 nsIntRect aRect = nsIntRect());
     void RemoveScreen(uint32_t aScreenId);