bug 702330 - Revert to drawing Flash plugin with a SurfaceView r=blassey
authorJames Willcox <jwillcox@mozilla.com>
Tue, 15 Nov 2011 10:43:42 -0500
changeset 83465 bbde0864db917990ce28b70988109d311a7b66e6
parent 83464 6b776bed41d7f1fea5fe28c46f2473637147de83
child 83466 644973d65be727d95388ca8df8c7e69f8bc9a224
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs702330
milestone11.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 702330 - Revert to drawing Flash plugin with a SurfaceView r=blassey
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,144 +37,147 @@
  * ***** 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 surfaceInfoCls;
-  jmethodID getSurfaceInfo;
+  jclass lockInfoCls;
+  jmethodID lockSurfaceANP;
+  jmethodID jUnlockSurfaceANP;
+  jfieldID jDirtyTop;
+  jfieldID jDirtyLeft;
+  jfieldID jDirtyBottom;
+  jfieldID jDirtyRight;
   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, 
-                                              "getSurfaceInfoClass",
+                                              "getSurfaceLockInfoClass",
                                               "()Ljava/lang/Class;");
 
-  gSurfaceJavaGlue.surfaceInfoCls = (jclass) env->NewGlobalRef(env->CallStaticObjectMethod(gSurfaceJavaGlue.geckoAppShellClass, getClass));
+  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.jFormat = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "format", "I");
-  gSurfaceJavaGlue.jWidth = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "width", "I");
-  gSurfaceJavaGlue.jHeight = env->GetFieldID(gSurfaceJavaGlue.surfaceInfoCls, "height", "I");
+  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.getSurfaceInfo = env->GetStaticMethodID(gSurfaceJavaGlue.geckoAppShellClass, "getSurfaceInfo", "(Landroid/view/SurfaceView;)Lorg/mozilla/gecko/SurfaceInfo;");
+  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.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.getSurfaceInfo, surfaceView);
+                                             gSurfaceJavaGlue.lockSurfaceANP, 
+                                             surfaceView, args[1].i, args[2].i, args[3].i, args[4].i);
 
   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;
-    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) {
+  }
+  else if (format & 0x00000004) {
     bitmap->format = kRGB_565_ANPBitmapFormat;
     bitmap->rowBytes = bitmap->width * 2;
-    targetFormat = gfxASurface::ImageFormatRGB16_565;
-  } else {
+  }
+  else {
     LOG("format from glue is unknown %d\n", format);
     return false;
   }
 
-  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;
-  }
+  jobject buf = env->GetObjectField(info, gSurfaceJavaGlue.jBuffer);
+  bitmap->baseAddr = env->GetDirectBufferAddress(buf);
   
-  gfxImageSurface* target = pinst->LockTargetSurface(bitmap->width, bitmap->height, targetFormat, &lockRect);
-  bitmap->baseAddr = target->Data();
-
+  LOG("format: %d, width: %d, height: %d",  bitmap->format,  bitmap->width,  bitmap->height);
   env->DeleteLocalRef(info);
-
-  return true;
+  env->DeleteLocalRef(buf);
+  return ( bitmap->width > 0 && bitmap->height > 0 );
 }
 
 static void anp_unlock(JNIEnv* env, jobject surfaceView) {
   LOG("%s", __PRETTY_FUNCTION__);
 
   if (!surfaceView) {
     LOG("null surface, exiting %s", __PRETTY_FUNCTION__);
     return;
   }
 
-  nsNPAPIPluginInstance* pinst = nsNPAPIPluginInstance::FindByJavaSurface((void*)surfaceView);
-  if (!pinst) {
-    LOG("Could not find plugin instance!");
-    return;
-  }
-  
-  pinst->UnlockTargetSurface(true /* invalidate the locked area */);
+  init(env);
+  env->CallStaticVoidMethod(gSurfaceJavaGlue.geckoAppShellClass, gSurfaceJavaGlue.jUnlockSurfaceANP, surfaceView);
+  LOG("returning from %s", __PRETTY_FUNCTION__);
+
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 #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,45 +60,40 @@
 #include "nsSize.h"
 #include "nsNetCID.h"
 #include "nsIContent.h"
 
 #ifdef MOZ_WIDGET_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 MOZ_WIDGET_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 MOZ_WIDGET_ANDROID
     mSurface(nsnull),
-    mTargetSurface(nsnull),
     mDrawingModel(0),
 #endif
     mRunning(NOT_STARTED),
     mWindowless(false),
     mWindowlessLocal(false),
     mTransparent(false),
     mCached(false),
     mUsesDOMForCursor(false),
@@ -123,47 +118,27 @@ 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 MOZ_WIDGET_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 MOZ_WIDGET_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;
 }
@@ -803,71 +778,19 @@ 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(MOZ_WIDGET_ANDROID)
   *aModel = (PRInt32)mDrawingModel;
   return NS_OK;
 #else
--- a/dom/plugins/base/nsNPAPIPluginInstance.h
+++ b/dom/plugins/base/nsNPAPIPluginInstance.h
@@ -45,26 +45,19 @@
 #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;
 
@@ -151,23 +144,16 @@ public:
 #ifdef XP_MACOSX
   void SetDrawingModel(NPDrawingModel aModel);
   void SetEventModel(NPEventModel aModel);
 #endif
 
 #ifdef MOZ_WIDGET_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();
 
@@ -285,18 +271,13 @@ private:
   // Timestamp for the last time this plugin was stopped.
   // This is only valid when the plugin is actually stopped!
   mozilla::TimeStamp mStopTime;
 
   nsCOMPtr<nsIURI> mURI;
 
   bool mUsePluginLayersPref;
 #ifdef MOZ_WIDGET_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
@@ -1668,37 +1668,16 @@ void nsPluginInstanceOwner::ScrollPositi
       }
       pluginWidget->EndDrawPlugin();
     }
   }
 #endif
 }
 
 #ifdef MOZ_WIDGET_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");
@@ -2830,41 +2809,93 @@ void nsPluginInstanceOwner::Paint(const 
   pluginEvent.wParam = (uint32)aHPS;
   pluginEvent.lParam = (uint32)&rectl;
   mInstance->HandleEvent(&pluginEvent, nsnull);
 }
 #endif
 
 #ifdef MOZ_WIDGET_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) {
-    AddPluginView(aFrameRect);
-
-    gfxImageSurface* pluginSurface = mInstance->LockTargetSurface();
-    if (!pluginSurface) {
-      mInstance->UnlockTargetSurface(false);
-      return;
+
+    {
+      ANPEvent event;
+      event.inSize = sizeof(ANPEvent);
+      event.eventType = kLifecycle_ANPEventType;
+      event.data.lifecycle.action = kOnScreen_ANPLifecycleAction;
+      mInstance->HandleEvent(&event, nsnull);
     }
 
-    aContext->SetOperator(gfxContext::OPERATOR_SOURCE);
-    aContext->SetSource(pluginSurface, gfxPoint(aFrameRect.x, aFrameRect.y));
-    aContext->Clip(aDirtyRect);
-    aContext->Paint();
-
-    mInstance->UnlockTargetSurface(false);
+    /*
+    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);
     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
@@ -305,17 +305,16 @@ 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
@@ -1284,54 +1284,113 @@ 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;
     }
 
-    public static SurfaceInfo getSurfaceInfo(SurfaceView sview)
+    static HashMap<SurfaceView, SurfaceLockInfo> sSufaceMap = new HashMap<SurfaceView, SurfaceLockInfo>();
+
+    public static void lockSurfaceANP()
     {
-        Log.i("GeckoAppShell", "getSurfaceInfo " + 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);
         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;
-        } else {
-            Log.i("GeckoAppShell", "Unknown pixel format: " + format);
+
+        if (n == 0)
             return null;
+
+        SurfaceLockInfo info = sSufaceMap.get(sview);
+        if (info == null) {
+            info = new SurfaceLockInfo();
+            sSufaceMap.put(sview, info);
         }
 
-        SurfaceInfo info = new SurfaceInfo();
+        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();
 
-        Rect r = sview.getHolder().getSurfaceFrame();
-        info.width = r.right;
-        info.height = r.bottom;
+            // 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);
+
         info.format = format;
+        info.dirtyTop = top;
+        info.dirtyBottom = bottom;
+        info.dirtyLeft = left;
+        info.dirtyRight = right;
 
         return info;
     }
 
-    public static Class getSurfaceInfoClass() {
-        Log.i("GeckoAppShell", "class name: " + SurfaceInfo.class.getName());
-        return SurfaceInfo.class;
+    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;
     }
 
     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
@@ -58,17 +58,17 @@ JAVAFILES = \
   GeckoAppShell.java \
   GeckoConnectivityReceiver.java \
   GeckoEvent.java \
   GeckoEventListener.java \
   GeckoInputConnection.java \
   GeckoPreferences.java \
   GlobalHistory.java \
   PromptService.java \
-  SurfaceInfo.java \
+  SurfaceLockInfo.java \
   Tab.java \
   Tabs.java \
   TabsTray.java \
   GeckoBatteryManager.java \
   GeckoThread.java \
   GeckoAsyncTask.java \
   gfx/BufferedCairoImage.java \
   gfx/CairoImage.java \
deleted file mode 100644
--- a/embedding/android/SurfaceInfo.java
+++ /dev/null
@@ -1,7 +0,0 @@
-package org.mozilla.gecko;
-
-public class SurfaceInfo {
-    public int format;
-    public int width;
-    public int height;
-}
new file mode 100644
--- /dev/null
+++ b/embedding/android/SurfaceLockInfo.java
@@ -0,0 +1,18 @@
+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;
+}