Bug 692198 - Make Flash on Android draw to bitmap intead of SurfaceView directly
authorJames Willcox <jwillcox@mozilla.com>
Wed, 05 Oct 2011 14:44:19 -0400
changeset 79588 33160751ee86ea422f157900f537ccc9167e89fc
parent 79587 96928459cadbe47b8148f21d143da7e87e046bc9
child 79589 630de2647c0b472a63e80313ab662c1a28a220e7
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs692198
milestone10.0a1
Bug 692198 - Make Flash on Android draw to bitmap intead of SurfaceView directly From 718909dd4d8c1b1ffb2e8ea72cc7d75c281e0773 Mon Sep 17 00:00:00 2001
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,144 @@
  * ***** 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) {
+    targetFormat = gfxASurface::ImageFormatARGB32;
+    */
+    
+    // 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;
-}