Bug 692198 - Make Flash on Android draw to bitmap intead of SurfaceView directly r=blassey
☠☠ backed out by 2f53f26d9e1b ☠ ☠
authorJames Willcox <jwillcox@mozilla.com>
Wed, 05 Oct 2011 14:44:19 -0400
changeset 80057 dcc28a7cfa318ff0dde12e0c0bd7cd5cd9e8341a
parent 80056 13342c7d1fc390ad45e64217c1511b9e4f114b9a
child 80058 40f077f9c4a2529d9fccb9f35e7fdc7fa101482d
push id434
push userclegnitto@mozilla.com
push dateWed, 21 Dec 2011 12:10:54 +0000
treeherdermozilla-beta@bddb6ed8dd47 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs692198
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 692198 - Make Flash on Android draw to bitmap intead of SurfaceView directly r=blassey commit 872c1f5bf1f2c205c3f999409ed55f31627c968a Author: James Willcox <jwillcox@mozilla.com> Bug 692198 - Make Flash on Android draw to bitmap intead of SurfaceView directly
dom/plugins/base/android/ANPSurface.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsNPAPIPluginInstance.h
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
embedding/android/GeckoAppShell.java
embedding/android/Makefile.in
embedding/android/SurfaceInfo.java
embedding/android/SurfaceLockInfo.java
--- a/dom/plugins/base/android/ANPSurface.cpp
+++ b/dom/plugins/base/android/ANPSurface.cpp
@@ -37,147 +37,138 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "assert.h"
 #include "ANPBase.h"
 #include <android/log.h>
 #include "AndroidBridge.h"
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
+#include "nsNPAPIPluginInstance.h"
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "GeckoPlugins" , ## args)
 #define ASSIGN(obj, name)   (obj)->name = anp_surface_##name
 
 
 // used to cache JNI method and field IDs for Surface Objects
 static struct ANPSurfaceInterfaceJavaGlue {
   bool        initialized;
   jclass geckoAppShellClass;
-  jclass lockInfoCls;
-  jmethodID lockSurfaceANP;
-  jmethodID jUnlockSurfaceANP;
-  jfieldID jDirtyTop;
-  jfieldID jDirtyLeft;
-  jfieldID jDirtyBottom;
-  jfieldID jDirtyRight;
+  jclass surfaceInfoCls;
+  jmethodID getSurfaceInfo;
   jfieldID jFormat;
   jfieldID jWidth ;
   jfieldID jHeight;
-  jfieldID jBuffer;
 } gSurfaceJavaGlue;
 
 #define getClassGlobalRef(env, cname)                                    \
      (jClass = jclass(env->NewGlobalRef(env->FindClass(cname))))
 
 static void init(JNIEnv* env) {
   if (gSurfaceJavaGlue.initialized)
     return;
   
   gSurfaceJavaGlue.geckoAppShellClass = mozilla::AndroidBridge::GetGeckoAppShellClass();
   
   jmethodID getClass = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, 
-                                              "getSurfaceLockInfoClass",
+                                              "getSurfaceInfoClass",
                                               "()Ljava/lang/Class;");
 
-  gSurfaceJavaGlue.lockInfoCls = (jclass) env->NewGlobalRef(env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass, getClass));
-
-  gSurfaceJavaGlue.jDirtyTop = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyTop", "I");
-  gSurfaceJavaGlue.jDirtyLeft = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyLeft", "I");
-  gSurfaceJavaGlue.jDirtyBottom = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyBottom", "I");
-  gSurfaceJavaGlue.jDirtyRight = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "dirtyRight", "I");
+  gSurfaceJavaGlue.surfaceInfoCls = (jclass) env->NewGlobalRef(env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass, getClass));
 
-  gSurfaceJavaGlue.jFormat = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "format", "I");
-  gSurfaceJavaGlue.jWidth = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "width", "I");
-  gSurfaceJavaGlue.jHeight = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "height", "I");
+  gSurfaceJavaGlue.jFormat = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "format", "I");
+  gSurfaceJavaGlue.jWidth = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "width", "I");
+  gSurfaceJavaGlue.jHeight = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "height", "I");
 
-  gSurfaceJavaGlue.jBuffer = env->GetFieldID(gSurfaceJavaGlue.lockInfoCls, "buffer", "Ljava/nio/Buffer;");
-  gSurfaceJavaGlue.lockSurfaceANP = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "lockSurfaceANP", "(Landroid/view/SurfaceView;IIII)Lorg/mozilla/gecko/SurfaceLockInfo;");
-  gSurfaceJavaGlue.jUnlockSurfaceANP = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "unlockSurfaceANP", "(Landroid/view/SurfaceView;)V");
+  gSurfaceJavaGlue.getSurfaceInfo = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "getSurfaceInfo", "(Landroid/view/SurfaceView;)Lorg/mozilla/gecko/SurfaceInfo;");
   gSurfaceJavaGlue.initialized = true;
 }
 
 static bool anp_lock(JNIEnv* env, jobject surfaceView, ANPBitmap* bitmap, ANPRectI* dirtyRect) {
   LOG("%s", __PRETTY_FUNCTION__);
   if (!bitmap || !surfaceView) {
     LOG("%s, null bitmap or surface, exiting", __PRETTY_FUNCTION__);
     return false;
   }
 
   init(env);
 
-  jvalue args[5];
-  args[0].l = surfaceView;
-  if (dirtyRect) {
-    args[1].i = dirtyRect->top;
-    args[2].i = dirtyRect->left;
-    args[3].i = dirtyRect->bottom;
-    args[4].i = dirtyRect->right;
-    LOG("dirty rect: %d, %d, %d, %d", dirtyRect->top, dirtyRect->left, dirtyRect->bottom, dirtyRect->right);
-  } else {
-    args[1].i = args[2].i = args[3].i = args[4].i = 0;
-  }
-  
   jobject info = env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass,
-                                             gSurfaceJavaGlue.lockSurfaceANP, 
-                                             surfaceView, args[1].i, args[2].i, args[3].i, args[4].i);
+                                             gSurfaceJavaGlue.getSurfaceInfo, surfaceView);
 
   LOG("info: %p", info);
   if (!info)
     return false;
 
-  // the surface may have expanded the dirty region so we must to pass that
-  // information back to the plugin.
-  if (dirtyRect) {
-    dirtyRect->left   = env->GetIntField(info, gSurfaceJavaGlue.jDirtyLeft);
-    dirtyRect->right  = env->GetIntField(info, gSurfaceJavaGlue.jDirtyRight);
-    dirtyRect->top    = env->GetIntField(info, gSurfaceJavaGlue.jDirtyTop);
-    dirtyRect->bottom = env->GetIntField(info, gSurfaceJavaGlue.jDirtyBottom);
-    LOG("dirty rect: %d, %d, %d, %d", dirtyRect->top, dirtyRect->left, dirtyRect->bottom, dirtyRect->right);
-  }
-
   bitmap->width  = env->GetIntField(info, gSurfaceJavaGlue.jWidth);
   bitmap->height = env->GetIntField(info, gSurfaceJavaGlue.jHeight);
 
+  if (bitmap->width <= 0 || bitmap->height <= 0)
+    return false;
+
   int format = env->GetIntField(info, gSurfaceJavaGlue.jFormat);
+  gfxImageFormat targetFormat;
 
   // format is PixelFormat
   if (format & 0x00000001) {
-    bitmap->format = kRGBA_8888_ANPBitmapFormat;
-    bitmap->rowBytes = bitmap->width * 4;
-  }
-  else if (format & 0x00000004) {
+    // We actually can't handle this right now because gfxImageSurface
+    // doesn't support RGBA32.
+    LOG("Unable to handle 32bit pixel format");
+    return false;
+  } else if (format & 0x00000004) {
     bitmap->format = kRGB_565_ANPBitmapFormat;
     bitmap->rowBytes = bitmap->width * 2;
-  }
-  else {
+    targetFormat = gfxASurface::ImageFormatRGB16_565;
+  } else {
     LOG("format from glue is unknown %d\n", format);
     return false;
   }
 
-  jobject buf = env->GetObjectField(info, gSurfaceJavaGlue.jBuffer);
-  bitmap->baseAddr = env->GetDirectBufferAddress(buf);
+  nsNPAPIPluginInstance* pinst = nsNPAPIPluginInstance::FindByJavaSurface((void*)surfaceView);
+  if (!pinst) {
+    LOG("Failed to get plugin instance");
+    return false;
+  }
+
+  NPRect lockRect;
+  if (dirtyRect) {
+    lockRect.top = dirtyRect->top;
+    lockRect.left = dirtyRect->left;
+    lockRect.right = dirtyRect->right;
+    lockRect.bottom = dirtyRect->bottom;
+  } else {
+    // No dirty rect, use the whole bitmap
+    lockRect.top = lockRect.left = 0;
+    lockRect.right = bitmap->width;
+    lockRect.bottom = bitmap->height;
+  }
   
-  LOG("format: %d, width: %d, height: %d",  bitmap->format,  bitmap->width,  bitmap->height);
+  gfxImageSurface* target = pinst->LockTargetSurface(bitmap->width, bitmap->height, targetFormat, &lockRect);
+  bitmap->baseAddr = target->Data();
+
   env->DeleteLocalRef(info);
-  env->DeleteLocalRef(buf);
-  return ( bitmap->width > 0 && bitmap->height > 0 );
+
+  return true;
 }
 
 static void anp_unlock(JNIEnv* env, jobject surfaceView) {
   LOG("%s", __PRETTY_FUNCTION__);
 
   if (!surfaceView) {
     LOG("null surface, exiting %s", __PRETTY_FUNCTION__);
     return;
   }
 
-  init(env);
-  env->CallStaticVoidMethod(gSurfaceJavaGlue.geckoAppShellClass, gSurfaceJavaGlue.jUnlockSurfaceANP, surfaceView);
-  LOG("returning from %s", __PRETTY_FUNCTION__);
-
+  nsNPAPIPluginInstance* pinst = nsNPAPIPluginInstance::FindByJavaSurface((void*)surfaceView);
+  if (!pinst) {
+    LOG("Could not find plugin instance!");
+    return;
+  }
+  
+  pinst->UnlockTargetSurface(true /* invalidate the locked area */);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 #define ASSIGN(obj, name)   (obj)->name = anp_##name
 
 void InitSurfaceInterface(ANPSurfaceInterfaceV0 *i) {
 
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -60,40 +60,45 @@
 #include "nsSize.h"
 #include "nsNetCID.h"
 #include "nsIContent.h"
 
 #ifdef ANDROID
 #include "ANPBase.h"
 #include <android/log.h>
 #include "android_npapi.h"
-#include "mozilla/Mutex.h"
 #include "mozilla/CondVar.h"
 #include "AndroidBridge.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::plugins::parent;
 
+#ifdef ANDROID
+#include <map>
+static std::map<void*, nsNPAPIPluginInstance*> sSurfaceMap;
+#endif
+
 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
 static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
 
 NS_IMPL_THREADSAFE_ISUPPORTS0(nsNPAPIPluginInstance)
 
 nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
   :
 #ifdef XP_MACOSX
 #ifdef NP_NO_QUICKDRAW
     mDrawingModel(NPDrawingModelCoreGraphics),
 #else
     mDrawingModel(NPDrawingModelQuickDraw),
 #endif
 #endif
 #ifdef ANDROID
     mSurface(nsnull),
+    mTargetSurface(nsnull),
     mDrawingModel(0),
 #endif
     mRunning(NOT_STARTED),
     mWindowless(false),
     mWindowlessLocal(false),
     mTransparent(false),
     mUsesDOMForCursor(false),
     mInPluginInitCall(false),
@@ -117,27 +122,47 @@ nsNPAPIPluginInstance::nsNPAPIPluginInst
   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
   if (prefs) {
     bool useLayersPref;
     nsresult rv = prefs->GetBoolPref("plugins.use_layers", &useLayersPref);
     if (NS_SUCCEEDED(rv))
       mUsePluginLayersPref = useLayersPref;
   }
 
+#ifdef ANDROID
+  mTargetSurfaceLock = new Mutex("nsNPAPIPluginInstance::SurfaceLock");
+#endif
+
   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance ctor: this=%p\n",this));
 }
 
 nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
 {
   PLUGIN_LOG(PLUGIN_LOG_BASIC, ("nsNPAPIPluginInstance dtor: this=%p\n",this));
 
   if (mMIMEType) {
     PR_Free((void *)mMIMEType);
     mMIMEType = nsnull;
   }
+
+#ifdef ANDROID
+  if (mSurface) {
+    sSurfaceMap.erase(mSurface);
+  }
+
+  if (mTargetSurface) {
+    delete mTargetSurface;
+    mTargetSurface = nsnull;
+  }
+
+  if (mTargetSurfaceLock) {
+    delete mTargetSurfaceLock;
+    mTargetSurfaceLock = nsnull;
+  }
+#endif
 }
 
 void
 nsNPAPIPluginInstance::Destroy()
 {
   Stop();
   mPlugin = nsnull;
 }
@@ -770,19 +795,71 @@ void* nsNPAPIPluginInstance::GetJavaSurf
   if (mDrawingModel != kSurface_ANPDrawingModel)
     return nsnull;
   
   if (mSurface)
     return mSurface;
 
   nsCOMPtr<SurfaceGetter> sg = new SurfaceGetter(mPlugin->PluginFuncs(), mNPP);
   mSurface = sg->GetSurface();
+  sSurfaceMap[mSurface] = this;
   return mSurface;
 }
 
+gfxImageSurface*
+nsNPAPIPluginInstance::LockTargetSurface()
+{
+  mTargetSurfaceLock->Lock();
+  return mTargetSurface;
+}
+
+gfxImageSurface*
+nsNPAPIPluginInstance::LockTargetSurface(PRUint32 aWidth, PRUint32 aHeight, gfxImageFormat aFormat,
+                                         NPRect* aRect)
+{
+  mTargetSurfaceLock->Lock();
+  if (!mTargetSurface ||
+      mTargetSurface->Width() != aWidth ||
+      mTargetSurface->Height() != aHeight ||
+      mTargetSurface->Format() != aFormat) {
+
+    if (mTargetSurface) {
+      delete mTargetSurface;
+    }
+
+    mTargetSurface = new gfxImageSurface(gfxIntSize(aWidth, aHeight), aFormat);
+  }
+
+  mTargetLockRect = *aRect;
+
+  return mTargetSurface;
+}
+
+void
+nsNPAPIPluginInstance::InvalidateTargetRect()
+{
+    InvalidateRect(&mTargetLockRect);
+}
+
+void
+nsNPAPIPluginInstance::UnlockTargetSurface(bool aInvalidate)
+{
+  mTargetSurfaceLock->Unlock();
+
+  if (aInvalidate) {
+    NS_DispatchToMainThread(NS_NewRunnableMethod(this, &nsNPAPIPluginInstance::InvalidateTargetRect));
+  }
+}
+
+nsNPAPIPluginInstance*
+nsNPAPIPluginInstance::FindByJavaSurface(void* aJavaSurface)
+{
+  return sSurfaceMap[aJavaSurface];
+}
+
 #endif
 
 nsresult nsNPAPIPluginInstance::GetDrawingModel(PRInt32* aModel)
 {
 #if defined(XP_MACOSX) || defined(ANDROID)
   *aModel = (PRInt32)mDrawingModel;
   return NS_OK;
 #else
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -45,19 +45,26 @@
 #include "nsPIDOMWindow.h"
 #include "nsITimer.h"
 #include "nsIPluginTagInfo.h"
 #include "nsIURI.h"
 #include "nsIChannel.h"
 #include "nsInterfaceHashtable.h"
 #include "nsHashKeys.h"
 
+#include "gfxASurface.h"
+#include "gfxImageSurface.h"
+
 #include "mozilla/TimeStamp.h"
 #include "mozilla/PluginLibrary.h"
 
+#ifdef ANDROID
+#include "mozilla/Mutex.h"
+#endif
+
 struct JSObject;
 
 class nsPluginStreamListenerPeer; // browser-initiated stream class
 class nsNPAPIPluginStreamListener; // plugin-initiated stream class
 class nsIPluginInstanceOwner;
 class nsIPluginStreamListener;
 class nsIOutputStream;
 
@@ -143,16 +150,23 @@ public:
 #ifdef XP_MACOSX
   void SetDrawingModel(NPDrawingModel aModel);
   void SetEventModel(NPEventModel aModel);
 #endif
 
 #ifdef ANDROID
   void SetDrawingModel(PRUint32 aModel);
   void* GetJavaSurface();
+
+  gfxImageSurface* LockTargetSurface();
+  gfxImageSurface* LockTargetSurface(PRUint32 aWidth, PRUint32 aHeight, gfxASurface::gfxImageFormat aFormat,
+                                     NPRect* aRect);
+  void UnlockTargetSurface(bool aInvalidate);
+
+  static nsNPAPIPluginInstance* FindByJavaSurface(void* aJavaSurface);
 #endif
 
   nsresult NewStreamListener(const char* aURL, void* notifyData,
                              nsIPluginStreamListener** listener);
 
   nsNPAPIPluginInstance(nsNPAPIPlugin* plugin);
   virtual ~nsNPAPIPluginInstance();
 
@@ -259,13 +273,18 @@ private:
 
   // non-null during a HandleEvent call
   void* mCurrentPluginEvent;
 
   nsCOMPtr<nsIURI> mURI;
 
   bool mUsePluginLayersPref;
 #ifdef ANDROID
+  void InvalidateTargetRect();
+  
   void* mSurface;
+  gfxImageSurface *mTargetSurface;
+  mozilla::Mutex* mTargetSurfaceLock;
+  NPRect mTargetLockRect;
 #endif
 };
 
 #endif // nsNPAPIPluginInstance_h_
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1666,16 +1666,37 @@ void nsPluginInstanceOwner::ScrollPositi
       }
       pluginWidget->EndDrawPlugin();
     }
   }
 #endif
 }
 
 #ifdef ANDROID
+void nsPluginInstanceOwner::AddPluginView(const gfxRect& aRect)
+{
+  void* javaSurface = mInstance->GetJavaSurface();
+
+  if (!javaSurface)
+    return;
+
+  JNIEnv* env = GetJNIForThread();
+  jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
+  jmethodID method = env->GetStaticMethodID(cls,
+                                            "addPluginView",
+                                            "(Landroid/view/View;DDDD)V");
+  env->CallStaticVoidMethod(cls,
+                            method,
+                            javaSurface,
+                            aRect.x,
+                            aRect.y,
+                            aRect.width,
+                            aRect.height);
+}
+
 void nsPluginInstanceOwner::RemovePluginView()
 {
   if (mInstance && mObjectFrame) {
     void* surface = mInstance->GetJavaSurface();
     if (surface) {
       JNIEnv* env = GetJNIForThread();
       if (env) {
         jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
@@ -2807,93 +2828,41 @@ void nsPluginInstanceOwner::Paint(const 
   pluginEvent.wParam = (uint32)aHPS;
   pluginEvent.lParam = (uint32)&rectl;
   mInstance->HandleEvent(&pluginEvent, nsnull);
 }
 #endif
 
 #ifdef ANDROID
 
-class AndroidPaintEventRunnable : public nsRunnable
-{
-public:
-  AndroidPaintEventRunnable(void* aSurface, nsNPAPIPluginInstance* inst, const gfxRect& aFrameRect)
-    : mSurface(aSurface), mInstance(inst), mFrameRect(aFrameRect) {
-  }
-
-  ~AndroidPaintEventRunnable() {
-  }
-
-  NS_IMETHOD Run()
-  {
-    LOG("%p - AndroidPaintEventRunnable::Run\n", this);
-
-    if (!mInstance || !mSurface)
-      return NS_OK;
-
-    // This needs to happen on the gecko main thread.
-    JNIEnv* env = GetJNIForThread();
-    jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
-    jmethodID method = env->GetStaticMethodID(cls,
-                                              "addPluginView",
-                                              "(Landroid/view/View;DDDD)V");
-    env->CallStaticVoidMethod(cls,
-                              method,
-                              mSurface,
-                              mFrameRect.x,
-                              mFrameRect.y,
-                              mFrameRect.width,
-                              mFrameRect.height);
-    return NS_OK;
-  }
-private:
-  void* mSurface;
-  nsCOMPtr<nsNPAPIPluginInstance> mInstance;
-  gfxRect mFrameRect;
-};
-
-
 void nsPluginInstanceOwner::Paint(gfxContext* aContext,
                                   const gfxRect& aFrameRect,
                                   const gfxRect& aDirtyRect)
 {
   if (!mInstance || !mObjectFrame)
     return;
 
   PRInt32 model;
   mInstance->GetDrawingModel(&model);
 
   if (model == kSurface_ANPDrawingModel) {
-
-    {
-      ANPEvent event;
-      event.inSize = sizeof(ANPEvent);
-      event.eventType = kLifecycle_ANPEventType;
-      event.data.lifecycle.action = kOnScreen_ANPLifecycleAction;
-      mInstance->HandleEvent(&event, nsnull);
+    AddPluginView(aFrameRect);
+
+    gfxImageSurface* pluginSurface = mInstance->LockTargetSurface();
+    if (!pluginSurface) {
+      mInstance->UnlockTargetSurface(false);
+      return;
     }
 
-    /*
-    gfxMatrix currentMatrix = aContext->CurrentMatrix();
-    gfxSize scale = currentMatrix.ScaleFactors(true);
-    printf_stderr("!!!!!!!! scale!!:  %f x %f\n", scale.width, scale.height);
-    */
-
-    JNIEnv* env = GetJNIForThread();
-    jclass cls = env->FindClass("org/mozilla/gecko/GeckoAppShell");
-    jmethodID method = env->GetStaticMethodID(cls,
-                                              "addPluginView",
-                                              "(Landroid/view/View;DDDD)V");
-    env->CallStaticVoidMethod(cls,
-                              method,
-                              mInstance->GetJavaSurface(),
-                              aFrameRect.x,
-                              aFrameRect.y,
-                              aFrameRect.width,
-                              aFrameRect.height);
+    aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
+    aContext->SetSource(pluginSurface, gfxPoint(aFrameRect.x, aFrameRect.y));
+    aContext->Clip(aDirtyRect);
+    aContext->Paint();
+
+    mInstance->UnlockTargetSurface(false);
     return;
   }
 
   if (model != kBitmap_ANPDrawingModel)
     return;
 
 #ifdef ANP_BITMAP_DRAWING_MODEL
   static nsRefPtr<gfxImageSurface> pluginSurface;
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -304,16 +304,17 @@ private:
   {
     nsIntSize size;
     return NS_SUCCEEDED(mInstance->GetImageSize(&size)) &&
     size == nsIntSize(mPluginWindow->width, mPluginWindow->height);
   }
   
   void FixUpURLS(const nsString &name, nsAString &value);
 #ifdef ANDROID
+  void AddPluginView(const gfxRect& aRect);
   void RemovePluginView();
 #endif 
  
   nsPluginNativeWindow       *mPluginWindow;
   nsRefPtr<nsNPAPIPluginInstance> mInstance;
   nsObjectFrame              *mObjectFrame; // owns nsPluginInstanceOwner
   nsCOMPtr<nsIContent>        mContent;
   nsCString                   mDocumentBase;
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -1350,20 +1350,17 @@ public class GeckoAppShell
         getMainHandler().post(new Runnable() { 
                 public void run() {
                     AbsoluteLayout.LayoutParams lp = new AbsoluteLayout.LayoutParams((int)w,
                                                                                      (int)h,
                                                                                      (int)x,
                                                                                      (int)y);
 
                     if (GeckoApp.mainLayout.indexOfChild(view) == -1) {
-                        view.setWillNotDraw(false);
-                        if(view instanceof SurfaceView)
-                            ((SurfaceView)view).setZOrderOnTop(true);
-
+                        view.setWillNotDraw(true);
                         GeckoApp.mainLayout.addView(view, lp);
                     }
                     else
                     {
                         try {
                             GeckoApp.mainLayout.updateViewLayout(view, lp);
                         } catch (IllegalArgumentException e) {
                             Log.i("updateViewLayout - IllegalArgumentException", "e:" + e);
@@ -1407,113 +1404,54 @@ public class GeckoAppShell
             Log.i("GeckoAppShell", "class not found", cnfe);
         } catch (android.content.pm.PackageManager.NameNotFoundException nnfe) {
             Log.i("GeckoAppShell", "package not found", nnfe);
         }
         Log.e("GeckoAppShell", "couldn't find class");
         return null;
     }
 
-    static HashMap<SurfaceView, SurfaceLockInfo> sSufaceMap = new HashMap<SurfaceView, SurfaceLockInfo>();
-
-    public static void lockSurfaceANP()
+    public static SurfaceInfo getSurfaceInfo(SurfaceView sview)
     {
-         Log.i("GeckoAppShell", "other lockSurfaceANP");
-    }
-
-    public static org.mozilla.gecko.SurfaceLockInfo lockSurfaceANP(android.view.SurfaceView sview, int top, int left, int bottom, int right)
-    {
-        Log.i("GeckoAppShell", "real lockSurfaceANP " + sview + ", " + top + ",  " + left + ", " + bottom + ", " + right);
+        Log.i("GeckoAppShell", "getSurfaceInfo " + sview);
         if (sview == null)
             return null;
 
         int format = -1;
         try {
             Field privateFormatField = SurfaceView.class.getDeclaredField("mFormat");
             privateFormatField.setAccessible(true);
             format = privateFormatField.getInt(sview);
         } catch (Exception e) {
             Log.i("GeckoAppShell", "mFormat is not a field of sview: ", e);
         }
 
         int n = 0;
-        if (format == PixelFormat.RGB_565)
+        if (format == PixelFormat.RGB_565) {
             n = 2;
-        else if (format == PixelFormat.RGBA_8888)
+        } else if (format == PixelFormat.RGBA_8888) {
             n = 4;
-
-        if (n == 0)
+        } else {
+            Log.i("GeckoAppShell", "Unknown pixel format: " + format);
             return null;
-
-        SurfaceLockInfo info = sSufaceMap.get(sview);
-        if (info == null) {
-            info = new SurfaceLockInfo();
-            sSufaceMap.put(sview, info);
         }
 
-        Rect r = new Rect(left, top, right, bottom);
-
-        info.canvas = sview.getHolder().lockCanvas(r);
-        int bufSizeRequired = info.canvas.getWidth() * info.canvas.getHeight() * n;
-        Log.i("GeckoAppShell", "lockSurfaceANP - bufSizeRequired: " + n + " " + info.canvas.getHeight() + " " + info.canvas.getWidth());
-
-        if (info.width != info.canvas.getWidth() || info.height != info.canvas.getHeight() || info.buffer == null || info.buffer.capacity() < bufSizeRequired) {
-            info.width = info.canvas.getWidth();
-            info.height = info.canvas.getHeight();
+        SurfaceInfo info = new SurfaceInfo();
 
-            // XXX Bitmaps instead of ByteBuffer
-            info.buffer = ByteBuffer.allocateDirect(bufSizeRequired);  //leak
-            Log.i("GeckoAppShell", "!!!!!!!!!!!  lockSurfaceANP - Allocating buffer! " + bufSizeRequired);
-
-        }
-
-        info.canvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR);
-
+        Rect r = sview.getHolder().getSurfaceFrame();
+        info.width = r.right;
+        info.height = r.bottom;
         info.format = format;
-        info.dirtyTop = top;
-        info.dirtyBottom = bottom;
-        info.dirtyLeft = left;
-        info.dirtyRight = right;
 
         return info;
     }
 
-    public static void unlockSurfaceANP(SurfaceView sview) {
-        SurfaceLockInfo info = sSufaceMap.get(sview);
-
-        int n = 0;
-        Bitmap.Config config;
-        if (info.format == PixelFormat.RGB_565) {
-            n = 2;
-            config = Bitmap.Config.RGB_565;
-        } else {
-            n = 4;
-            config = Bitmap.Config.ARGB_8888;
-        }
-
-        Log.i("GeckoAppShell", "unlockSurfaceANP: " + (info.width * info.height * n));
-
-        Bitmap bm = Bitmap.createBitmap(info.width, info.height, config);
-        bm.copyPixelsFromBuffer(info.buffer);
-        info.canvas.drawBitmap(bm, 0, 0, null);
-        sview.getHolder().unlockCanvasAndPost(info.canvas);
-    }
-
-    public static Class getSurfaceLockInfoClass() {
-        Log.i("GeckoAppShell", "class name: " + SurfaceLockInfo.class.getName());
-        return SurfaceLockInfo.class;
-    }
-
-    public static Method getSurfaceLockMethod() {
-        Method[] m = GeckoAppShell.class.getMethods();
-        for (int i = 0; i < m.length; i++) {
-            if (m[i].getName().equals("lockSurfaceANP"))
-                return m[i];
-        }
-        return null;
+    public static Class getSurfaceInfoClass() {
+        Log.i("GeckoAppShell", "class name: " + SurfaceInfo.class.getName());
+        return SurfaceInfo.class;
     }
 
     static native void executeNextRunnable();
 
     static class GeckoRunnableCallback implements Runnable {
         public void run() {
             Log.i("GeckoShell", "run GeckoRunnableCallback");
             GeckoAppShell.executeNextRunnable();
--- a/embedding/android/Makefile.in
+++ b/embedding/android/Makefile.in
@@ -48,17 +48,17 @@ DIRS = locales
 JAVAFILES = \
   GeckoApp.java \
   GeckoAppShell.java \
   GeckoConnectivityReceiver.java \
   GeckoEvent.java \
   GeckoSurfaceView.java \
   GeckoInputConnection.java \
   AlertNotification.java \
-  SurfaceLockInfo.java \
+  SurfaceInfo.java \
   $(NULL)
 
 PROCESSEDJAVAFILES = \
   App.java \
   Restarter.java \
   NotificationHandler.java \
   LauncherShortcuts.java \
   $(NULL)
new file mode 100644
--- /dev/null
+++ b/embedding/android/SurfaceInfo.java
@@ -0,0 +1,7 @@
+package org.mozilla.gecko;
+
+public class SurfaceInfo {
+    public int format;
+    public int width;
+    public int height;
+}
deleted file mode 100644
--- a/embedding/android/SurfaceLockInfo.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package org.mozilla.gecko;
-
-import android.graphics.Canvas;
-import java.nio.Buffer;
-
-public class SurfaceLockInfo {
-    public int dirtyTop;
-    public int dirtyLeft;
-    public int dirtyRight;
-    public int dirtyBottom;
-
-    public int bpr;
-    public int format;
-    public int width;
-    public int height;
-    public Buffer buffer;
-    public Canvas canvas;
-}