Bug 1322650 - Adjust Android Flash support to API changes r=jchen draft
authorJames Willcox <snorp@snorp.net>
Thu, 09 Mar 2017 17:51:17 -0600
changeset 568956 955f2d52640703d967eafbf9cb4c7c054e4f2b7a
parent 568955 5f7dad5981f69043a43f59a3723a293566a39c59
child 568957 9c7c15e4d98c9138afabd9681aa9fd5df0c34134
push id56033
push userbmo:snorp@snorp.net
push dateWed, 26 Apr 2017 20:29:44 +0000
reviewersjchen
bugs1322650
milestone55.0a1
Bug 1322650 - Adjust Android Flash support to API changes r=jchen MozReview-Commit-ID: CmMINaGcTER
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
gfx/gl/AndroidNativeWindow.h
mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceTextureListener.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/JNIObject.java
widget/android/jni/Natives.h
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -53,16 +53,18 @@ using namespace mozilla::dom;
 #include "mozilla/CondVar.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "mozilla/Hal.h"
 #include "GLContextProvider.h"
 #include "GLContext.h"
 #include "TexturePoolOGL.h"
 #include "SurfaceTypes.h"
 #include "EGLUtils.h"
+#include "GeneratedJNIWrappers.h"
+#include "GeneratedJNINatives.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 
 typedef nsNPAPIPluginInstance::VideoInfo VideoInfo;
 
 class PluginEventRunnable : public Runnable
 {
@@ -101,17 +103,17 @@ static bool EnsureGLContext()
     sPluginContext = GLContextProvider::CreateHeadless(flags, &discardedFailureId);
   }
 
   return sPluginContext != nullptr;
 }
 
 static std::map<NPP, nsNPAPIPluginInstance*> sPluginNPPMap;
 
-#endif
+#endif // MOZ_WIDGET_ANDROID
 
 using namespace mozilla;
 using namespace mozilla::plugins::parent;
 using namespace mozilla::layers;
 
 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
 
 NS_IMPL_ISUPPORTS(nsNPAPIPluginInstance, nsIAudioChannelAgentCallback)
@@ -197,24 +199,22 @@ uint32_t nsNPAPIPluginInstance::gInUnsaf
 void
 nsNPAPIPluginInstance::Destroy()
 {
   Stop();
   mPlugin = nullptr;
   mAudioChannelAgent = nullptr;
 
 #if MOZ_WIDGET_ANDROID
-  if (mContentSurface)
-    mContentSurface->SetFrameAvailableCallback(nullptr);
-
-  mContentSurface = nullptr;
+  if (mContentSurface) {
+    java::SurfaceAllocator::DisposeSurface(mContentSurface);
+  }
 
   std::map<void*, VideoInfo*>::iterator it;
   for (it = mVideos.begin(); it != mVideos.end(); it++) {
-    it->second->mSurfaceTexture->SetFrameAvailableCallback(nullptr);
     delete it->second;
   }
   mVideos.clear();
   SetWakeLock(false);
 #endif
 }
 
 TimeStamp
@@ -853,73 +853,93 @@ void nsNPAPIPluginInstance::SetWakeLock(
 GLContext* nsNPAPIPluginInstance::GLContext()
 {
   if (!EnsureGLContext())
     return nullptr;
 
   return sPluginContext;
 }
 
-already_AddRefed<AndroidSurfaceTexture> nsNPAPIPluginInstance::CreateSurfaceTexture()
+class PluginTextureListener
+  : public java::SurfaceTextureListener::Natives<PluginTextureListener>
 {
-  if (!EnsureGLContext())
-    return nullptr;
+  using Base = java::SurfaceTextureListener::Natives<PluginTextureListener>;
+
+  const nsCOMPtr<nsIRunnable> mCallback;
+public:
+  using Base::AttachNative;
+  using Base::DisposeNative;
+
+  PluginTextureListener(nsIRunnable* aCallback) : mCallback(aCallback) {}
 
-  GLuint texture = TexturePoolOGL::AcquireTexture();
-  if (!texture)
-    return nullptr;
+  void OnFrameAvailable()
+  {
+    if (NS_IsMainThread()) {
+      mCallback->Run();
+      return;
+    }
+    NS_DispatchToMainThread(mCallback);
+  }
+};
 
-  RefPtr<AndroidSurfaceTexture> surface = AndroidSurfaceTexture::Create(TexturePoolOGL::GetGLContext(),
-                                                                        texture);
-  if (!surface) {
+java::GeckoSurface::LocalRef nsNPAPIPluginInstance::CreateSurface()
+{
+  java::GeckoSurface::LocalRef surf = java::SurfaceAllocator::AcquireSurface(0, 0, false);
+  if (!surf) {
     return nullptr;
   }
 
   nsCOMPtr<nsIRunnable> frameCallback = NewRunnableMethod(this, &nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable);
-  surface->SetFrameAvailableCallback(frameCallback);
-  return surface.forget();
+
+  java::SurfaceTextureListener::LocalRef listener = java::SurfaceTextureListener::New();
+
+  PluginTextureListener::AttachNative(listener, MakeUnique<PluginTextureListener>(frameCallback.get()));
+
+  java::GeckoSurfaceTexture::LocalRef gst = java::GeckoSurfaceTexture::Lookup(surf->GetHandle());
+  if (!gst) {
+    return nullptr;
+  }
+
+  const auto& st = java::sdk::SurfaceTexture::Ref::From(gst);
+  st->SetOnFrameAvailableListener(listener);
+
+  return surf;
 }
 
 void nsNPAPIPluginInstance::OnSurfaceTextureFrameAvailable()
 {
   if (mRunning == RUNNING && mOwner)
     mOwner->Recomposite();
 }
 
 void* nsNPAPIPluginInstance::AcquireContentWindow()
 {
-  if (!mContentSurface) {
-    mContentSurface = CreateSurfaceTexture();
-
+  if (!mContentWindow.NativeWindow()) {
+    mContentSurface = CreateSurface();
     if (!mContentSurface)
       return nullptr;
+
+    mContentWindow = AndroidNativeWindow(mContentSurface);
   }
 
-  return mContentSurface->NativeWindow();
+  return mContentWindow.NativeWindow();
 }
 
-AndroidSurfaceTexture*
-nsNPAPIPluginInstance::AsSurfaceTexture()
+java::GeckoSurface::Param
+nsNPAPIPluginInstance::AsSurface()
 {
-  if (!mContentSurface)
-    return nullptr;
-
   return mContentSurface;
 }
 
 void* nsNPAPIPluginInstance::AcquireVideoWindow()
 {
-  RefPtr<AndroidSurfaceTexture> surface = CreateSurfaceTexture();
-  if (!surface) {
-    return nullptr;
-  }
-
+  java::GeckoSurface::LocalRef surface = CreateSurface();
   VideoInfo* info = new VideoInfo(surface);
 
-  void* window = info->mSurfaceTexture->NativeWindow();
+  void* window = info->mNativeWindow.NativeWindow();
   mVideos.insert(std::pair<void*, VideoInfo*>(window, info));
 
   return window;
 }
 
 void nsNPAPIPluginInstance::ReleaseVideoWindow(void* window)
 {
   std::map<void*, VideoInfo*>::iterator it = mVideos.find(window);
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -16,17 +16,17 @@
 #include "nsIChannel.h"
 #include "nsHashKeys.h"
 #include <prinrval.h>
 #include "js/TypeDecls.h"
 #include "nsIAudioChannelAgent.h"
 #ifdef MOZ_WIDGET_ANDROID
 #include "nsIRunnable.h"
 #include "GLContextTypes.h"
-#include "AndroidSurfaceTexture.h"
+#include "AndroidNativeWindow.h"
 #include "AndroidBridge.h"
 #include <map>
 class PluginEventRunnable;
 #endif
 
 #include "mozilla/EventForwards.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/PluginLibrary.h"
@@ -210,32 +210,34 @@ public:
     int32_t mWidth;
     int32_t mHeight;
     GLuint mInternalFormat;
   };
 
   // For ANPNativeWindow
   void* AcquireContentWindow();
 
-  mozilla::gl::AndroidSurfaceTexture* AsSurfaceTexture();
+  mozilla::java::GeckoSurface::Param AsSurface();
 
   // For ANPVideo
   class VideoInfo {
   public:
-    VideoInfo(mozilla::gl::AndroidSurfaceTexture* aSurfaceTexture) :
-      mSurfaceTexture(aSurfaceTexture)
+    VideoInfo(mozilla::java::GeckoSurface::Param aSurface)
+      : mSurface(aSurface)
+      , mNativeWindow(aSurface)
     {
     }
 
     ~VideoInfo()
     {
-      mSurfaceTexture = nullptr;
+      mozilla::java::SurfaceAllocator::DisposeSurface(mSurface);
     }
 
-    RefPtr<mozilla::gl::AndroidSurfaceTexture> mSurfaceTexture;
+    mozilla::java::GeckoSurface::GlobalRef mSurface;
+    mozilla::gl::AndroidNativeWindow mNativeWindow;
     gfxRect mDimensions;
   };
 
   void* AcquireVideoWindow();
   void ReleaseVideoWindow(void* aWindow);
   void SetVideoDimensions(void* aWindow, gfxRect aDimensions);
 
   void GetVideos(nsTArray<VideoInfo*>& aVideos);
@@ -354,17 +356,18 @@ protected:
   void PopPostedEvent(PluginEventRunnable* r);
   void OnSurfaceTextureFrameAvailable();
 
   uint32_t mFullScreenOrientation;
   bool mWakeLocked;
   bool mFullScreen;
   mozilla::gl::OriginPos mOriginPos;
 
-  RefPtr<mozilla::gl::AndroidSurfaceTexture> mContentSurface;
+  mozilla::java::GeckoSurface::GlobalRef mContentSurface;
+  mozilla::gl::AndroidNativeWindow mContentWindow;
 #endif
 
   enum {
     NOT_STARTED,
     RUNNING,
     DESTROYING,
     DESTROYED
   } mRunning;
@@ -404,18 +407,17 @@ private:
   void* mCurrentPluginEvent;
 #endif
 
   // Timestamp for the last time this plugin was stopped.
   // This is only valid when the plugin is actually stopped!
   mozilla::TimeStamp mStopTime;
 
 #ifdef MOZ_WIDGET_ANDROID
-  already_AddRefed<mozilla::gl::AndroidSurfaceTexture> CreateSurfaceTexture();
-
+  mozilla::java::GeckoSurface::LocalRef CreateSurface();
   std::map<void*, VideoInfo*> mVideos;
   bool mOnScreen;
 
   nsIntSize mCurrentSize;
 #endif
 
   // is this instance Java and affected by bug 750480?
   bool mHaveJavaC2PJSObjectQuirk;
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -164,32 +164,33 @@ nsPluginInstanceOwner::NotifyPaintWaiter
     // receive it immediately
     nsContentUtils::AddScriptRunner(event);
     mWaitingForPaint = true;
   }
 }
 
 #if MOZ_WIDGET_ANDROID
 static void
-AttachToContainerAsSurfaceTexture(ImageContainer* container,
-                                  nsNPAPIPluginInstance* instance,
-                                  const LayoutDeviceRect& rect,
-                                  RefPtr<Image>* out_image)
+AttachToContainerAsSurface(ImageContainer* container,
+                           nsNPAPIPluginInstance* instance,
+                           const LayoutDeviceRect& rect,
+                           RefPtr<Image>* out_image)
 {
   MOZ_ASSERT(out_image);
   MOZ_ASSERT(!*out_image);
 
-  mozilla::gl::AndroidSurfaceTexture* surfTex = instance->AsSurfaceTexture();
-  if (!surfTex) {
+  java::GeckoSurface::LocalRef surface = instance->AsSurface();
+  if (!surface) {
     return;
   }
 
   RefPtr<Image> img = new SurfaceTextureImage(
-    surfTex,
+    surface->GetHandle(),
     gfx::IntSize::Truncate(rect.width, rect.height),
+    true, // continuously update without a transaction
     instance->OriginPos());
   *out_image = img;
 }
 #endif
 
 bool
 nsPluginInstanceOwner::NeedsScrollImageLayer()
 {
@@ -222,17 +223,17 @@ nsPluginInstanceOwner::GetImageContainer
   ScreenSize screenSize = (r * LayoutDeviceToScreenScale(resolution)).Size();
   mInstance->NotifySize(nsIntSize::Truncate(screenSize.width, screenSize.height));
 
   container = LayerManager::CreateImageContainer();
 
   if (r.width && r.height) {
     // Try to get it as an EGLImage first.
     RefPtr<Image> img;
-    AttachToContainerAsSurfaceTexture(container, mInstance, r, &img);
+    AttachToContainerAsSurface(container, mInstance, r, &img);
 
     if (img) {
       container->SetCurrentImageInTransaction(img);
     }
   }
 #else
   if (NeedsScrollImageLayer()) {
     // windowed plugin under e10s
@@ -1577,18 +1578,19 @@ nsPluginInstanceOwner::GetVideos(nsTArra
 
 already_AddRefed<ImageContainer>
 nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
 {
   RefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
 
   if (aVideoInfo->mDimensions.width && aVideoInfo->mDimensions.height) {
     RefPtr<Image> img = new SurfaceTextureImage(
-      aVideoInfo->mSurfaceTexture,
+      aVideoInfo->mSurface->GetHandle(),
       gfx::IntSize::Truncate(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height),
+      true, /* continuous */
       gl::OriginPos::BottomLeft);
     container->SetCurrentImageInTransaction(img);
   }
 
   return container.forget();
 }
 
 void nsPluginInstanceOwner::Invalidate() {
--- a/gfx/gl/AndroidNativeWindow.h
+++ b/gfx/gl/AndroidNativeWindow.h
@@ -14,16 +14,19 @@
 #include "GeneratedJNIWrappers.h"
 #include "SurfaceTexture.h"
 
 namespace mozilla {
 namespace gl {
 
 class AndroidNativeWindow {
 public:
+  AndroidNativeWindow() : mNativeWindow(nullptr) {
+  }
+
   AndroidNativeWindow(java::sdk::Surface::Param aSurface) {
     mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
                                               aSurface.Get());
   }
 
   AndroidNativeWindow(java::GeckoSurface::Param aSurface) {
     auto surf = java::sdk::Surface::LocalRef(java::sdk::Surface::Ref::From(aSurface));
     mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceTextureListener.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceTextureListener.java
@@ -12,20 +12,22 @@ import android.graphics.SurfaceTexture;
 
 final class SurfaceTextureListener
     extends JNIObject implements SurfaceTexture.OnFrameAvailableListener
 {
     @WrapForJNI(calledFrom = "gecko")
     private SurfaceTextureListener() {
     }
 
+    @WrapForJNI(dispatchTo = "gecko") @Override // JNIObject
+    protected native void disposeNative();
+
     @Override
-    protected void disposeNative() {
-        // SurfaceTextureListener is disposed inside AndroidSurfaceTexture.
-        throw new IllegalStateException("unreachable code");
+    protected void finalize() {
+        disposeNative();
     }
 
     @WrapForJNI(stubName = "OnFrameAvailable")
     private native void nativeOnFrameAvailable();
 
     @Override // SurfaceTexture.OnFrameAvailableListener
     public void onFrameAvailable(SurfaceTexture surfaceTexture) {
         try {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/JNIObject.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/mozglue/JNIObject.java
@@ -2,10 +2,15 @@ package org.mozilla.gecko.mozglue;
 
 // Class that all classes with native methods extend from.
 public abstract class JNIObject
 {
     // Pointer to a WeakPtr object that refers to the native object.
     private long mHandle;
 
     // Dispose of any reference to a native object.
+    //
+    // If the native instance is destroyed from the native side, this should never be
+    // called, so you should throw an UnsupportedOperationException. If instead you
+    // want to destroy the native side from the Java end, make override this with
+    // a native call, and the right thing will be done in the native code.
     protected abstract void disposeNative();
 }
--- a/widget/android/jni/Natives.h
+++ b/widget/android/jni/Natives.h
@@ -39,17 +39,17 @@ namespace jni {
  *       // ...
  *
  *   public:
  *       MOZ_DECLARE_WEAKREFERENCE_TYPENAME(MyClass)
  *       using MyJavaClass::Natives<MyClass>::DisposeNative;
  *
  *       void AttachTo(const MyJavaClass::LocalRef& instance)
  *       {
- *           MyJavaClass::Natives<MyClass>::AttachInstance(
+ *           MyJavaClass::Natives<MyClass>::AttachNative(
  *                   instance, static_cast<SupportsWeakPtr<MyClass>*>(this));
  *
  *           // "instance" does NOT own "this", so the C++ object
  *           // lifetime is separate from the Java object lifetime.
  *       }
  *   };
  *
  * * If the C++ class contains public members AddRef() and Release(), the Java
@@ -65,17 +65,17 @@ namespace jni {
  *   {
  *       // ...
  *
  *   public:
  *       using MyJavaClass::Natives<MyClass>::DisposeNative;
  *
  *       void AttachTo(const MyJavaClass::LocalRef& instance)
  *       {
- *           MyJavaClass::Natives<MyClass>::AttachInstance(instance, this);
+ *           MyJavaClass::Natives<MyClass>::AttachNative(instance, this);
  *
  *           // "instance" owns "this" through the RefPtr, so the C++ object
  *           // may be destroyed as soon as instance.disposeNative() is called.
  *       }
  *   };
  *
  * * In other cases, the Java instance will store and own a pointer to the C++
  *   object itself. This pointer must not be stored or deleted elsewhere. To
@@ -86,17 +86,17 @@ namespace jni {
  *   {
  *       // ...
  *
  *   public:
  *       using MyJavaClass::Natives<MyClass>::DisposeNative;
  *
  *       static void AttachTo(const MyJavaClass::LocalRef& instance)
  *       {
- *           MyJavaClass::Natives<MyClass>::AttachInstance(
+ *           MyJavaClass::Natives<MyClass>::AttachNative(
  *                   instance, mozilla::MakeUnique<MyClass>());
  *
  *           // "instance" owns the newly created C++ object, so the C++
  *           // object is destroyed as soon as instance.disposeNative() is
  *           // called.
  *       }
  *   };
  */