Restructuring the sample plugin and adding more tests.
diff --git a/samples/SampleBrowserPlugin/Android.mk b/samples/BrowserPlugin/Android.mk
similarity index 100%
rename from samples/SampleBrowserPlugin/Android.mk
rename to samples/BrowserPlugin/Android.mk
diff --git a/samples/SampleBrowserPlugin/AndroidManifest.xml b/samples/BrowserPlugin/AndroidManifest.xml
similarity index 100%
rename from samples/SampleBrowserPlugin/AndroidManifest.xml
rename to samples/BrowserPlugin/AndroidManifest.xml
diff --git a/samples/SampleBrowserPlugin/MODULE_LICENSE_APACHE2 b/samples/BrowserPlugin/MODULE_LICENSE_APACHE2
similarity index 100%
rename from samples/SampleBrowserPlugin/MODULE_LICENSE_APACHE2
rename to samples/BrowserPlugin/MODULE_LICENSE_APACHE2
diff --git a/samples/SampleBrowserPlugin/NOTICE b/samples/BrowserPlugin/NOTICE
similarity index 100%
rename from samples/SampleBrowserPlugin/NOTICE
rename to samples/BrowserPlugin/NOTICE
diff --git a/samples/SampleBrowserPlugin/jni/Android.mk b/samples/BrowserPlugin/jni/Android.mk
similarity index 93%
rename from samples/SampleBrowserPlugin/jni/Android.mk
rename to samples/BrowserPlugin/jni/Android.mk
index 6d99737..ae35ed4 100644
--- a/samples/SampleBrowserPlugin/jni/Android.mk
+++ b/samples/BrowserPlugin/jni/Android.mk
@@ -30,10 +30,13 @@
 LOCAL_SRC_FILES := \
 	main.cpp \
 	PluginObject.cpp \
-	pluginGraphics.cpp
+	animation/AnimationPlugin.cpp \
+	background/BackgroundPlugin.cpp 
 
 LOCAL_C_INCLUDES += \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/animation \
+	$(LOCAL_PATH)/background \
 	external/webkit/WebCore/bridge \
 	external/webkit/WebCore/plugins \
 	external/webkit/WebCore/platform/android/JavaVM \
diff --git a/samples/SampleBrowserPlugin/jni/PluginObject.cpp b/samples/BrowserPlugin/jni/PluginObject.cpp
similarity index 89%
rename from samples/SampleBrowserPlugin/jni/PluginObject.cpp
rename to samples/BrowserPlugin/jni/PluginObject.cpp
index 5499072..80f5e7c 100644
--- a/samples/SampleBrowserPlugin/jni/PluginObject.cpp
+++ b/samples/BrowserPlugin/jni/PluginObject.cpp
@@ -1,33 +1,33 @@
 /*
  IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
- consideration of your agreement to the following terms, and your use, installation, 
- modification or redistribution of this Apple software constitutes acceptance of these 
- terms.  If you do not agree with these terms, please do not use, install, modify or 
+ consideration of your agreement to the following terms, and your use, installation,
+ modification or redistribution of this Apple software constitutes acceptance of these
+ terms.  If you do not agree with these terms, please do not use, install, modify or
  redistribute this Apple software.
- 
- In consideration of your agreement to abide by the following terms, and subject to these 
- terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in 
- this original Apple software (the "Apple Software"), to use, reproduce, modify and 
- redistribute the Apple Software, with or without modifications, in source and/or binary 
- forms; provided that if you redistribute the Apple Software in its entirety and without 
- modifications, you must retain this notice and the following text and disclaimers in all 
- such redistributions of the Apple Software.  Neither the name, trademarks, service marks 
- or logos of Apple Computer, Inc. may be used to endorse or promote products derived from 
+
+ In consideration of your agreement to abide by the following terms, and subject to these
+ terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in
+ this original Apple software (the "Apple Software"), to use, reproduce, modify and
+ redistribute the Apple Software, with or without modifications, in source and/or binary
+ forms; provided that if you redistribute the Apple Software in its entirety and without
+ modifications, you must retain this notice and the following text and disclaimers in all
+ such redistributions of the Apple Software.  Neither the name, trademarks, service marks
+ or logos of Apple Computer, Inc. may be used to endorse or promote products derived from
  the Apple Software without specific prior written permission from Apple. Except as expressly
  stated in this notice, no other rights or licenses, express or implied, are granted by Apple
- herein, including but not limited to any patent rights that may be infringed by your 
+ herein, including but not limited to any patent rights that may be infringed by your
  derivative works or by other works in which the Apple Software may be incorporated.
- 
- The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES, 
- EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, 
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS 
+
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES,
+ EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS
  USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
- 
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL 
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
-          OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, 
- REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND 
- WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR 
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+          OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
+ REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND
+ WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
  OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
@@ -49,10 +49,10 @@
 
 
 
-static NPClass pluginClass = { 
+static NPClass pluginClass = {
     NP_CLASS_STRUCT_VERSION,
-    pluginAllocate, 
-    pluginDeallocate, 
+    pluginAllocate,
+    pluginDeallocate,
     pluginInvalidate,
     pluginHasMethod,
     pluginInvoke,
@@ -63,7 +63,7 @@
     pluginRemoveProperty,
     pluginEnumerate
 };
- 
+
 NPClass *getPluginClass(void)
 {
     return &pluginClass;
@@ -150,18 +150,18 @@
     PluginObject *newInstance = (PluginObject*) malloc(sizeof(PluginObject));
     newInstance->header._class = theClass;
     newInstance->header.referenceCount = 1;
-    
+
     if (!identifiersInitialized) {
         identifiersInitialized = true;
         initializeIdentifiers();
     }
-    
+
     newInstance->npp = npp;
 
     return &newInstance->header;
 }
 
-static void pluginDeallocate(NPObject *obj) 
+static void pluginDeallocate(NPObject *obj)
 {
     free(obj);
 }
@@ -175,4 +175,3 @@
 {
     return false;
 }
-
diff --git a/samples/SampleBrowserPlugin/jni/PluginObject.h b/samples/BrowserPlugin/jni/PluginObject.h
similarity index 70%
rename from samples/SampleBrowserPlugin/jni/PluginObject.h
rename to samples/BrowserPlugin/jni/PluginObject.h
index ae8963d..8a9a079 100644
--- a/samples/SampleBrowserPlugin/jni/PluginObject.h
+++ b/samples/BrowserPlugin/jni/PluginObject.h
@@ -1,68 +1,76 @@
 /*
  IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
- consideration of your agreement to the following terms, and your use, installation, 
- modification or redistribution of this Apple software constitutes acceptance of these 
- terms.  If you do not agree with these terms, please do not use, install, modify or 
+ consideration of your agreement to the following terms, and your use, installation,
+ modification or redistribution of this Apple software constitutes acceptance of these
+ terms.  If you do not agree with these terms, please do not use, install, modify or
  redistribute this Apple software.
- 
- In consideration of your agreement to abide by the following terms, and subject to these 
- terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in 
- this original Apple software (the "Apple Software"), to use, reproduce, modify and 
- redistribute the Apple Software, with or without modifications, in source and/or binary 
- forms; provided that if you redistribute the Apple Software in its entirety and without 
- modifications, you must retain this notice and the following text and disclaimers in all 
- such redistributions of the Apple Software.  Neither the name, trademarks, service marks 
- or logos of Apple Computer, Inc. may be used to endorse or promote products derived from 
+
+ In consideration of your agreement to abide by the following terms, and subject to these
+ terms, Apple grants you a personal, non-exclusive license, under AppleÕs copyrights in
+ this original Apple software (the "Apple Software"), to use, reproduce, modify and
+ redistribute the Apple Software, with or without modifications, in source and/or binary
+ forms; provided that if you redistribute the Apple Software in its entirety and without
+ modifications, you must retain this notice and the following text and disclaimers in all
+ such redistributions of the Apple Software.  Neither the name, trademarks, service marks
+ or logos of Apple Computer, Inc. may be used to endorse or promote products derived from
  the Apple Software without specific prior written permission from Apple. Except as expressly
  stated in this notice, no other rights or licenses, express or implied, are granted by Apple
- herein, including but not limited to any patent rights that may be infringed by your 
+ herein, including but not limited to any patent rights that may be infringed by your
  derivative works or by other works in which the Apple Software may be incorporated.
- 
- The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES, 
- EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, 
- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS 
+
+ The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES,
+ EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT,
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS
  USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
- 
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL 
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
-          OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, 
- REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND 
- WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR 
+
+ IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+          OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE,
+ REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND
+ WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR
  OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef PluginObject__DEFINED
 #define PluginObject__DEFINED
 
-#include "npapi.h"
+#include "main.h"
 
+struct ANPEvent;
 struct ANPCanvas;
 struct ANPAudioTrack;
 
-class Animation {
+class SubPlugin {
 public:
-    Animation(NPP inst) : m_inst(inst) {}
-    virtual ~Animation() {}
+    SubPlugin(NPP inst) : m_inst(inst) {}
+    virtual ~SubPlugin() {}
     virtual void draw(ANPCanvas*) = 0;
-    
+    virtual int16 handleEvent(const ANPEvent* evt) = 0;
+
     NPP inst() const { return m_inst; }
-    
+
 private:
     NPP m_inst;
 };
 
+enum PluginTypes {
+    kBackground_PluginType = 1,
+    kAnimation_PluginType  = 2,
+    kAudio_PluginType      = 3,
+    kText_PluginType       = 4,
+    kPaint_PluginType      = 5
+};
+typedef uint32_t PluginType;
+
 typedef struct PluginObject {
     NPObject header;
     NPP npp;
     NPWindow* window;
-    Animation* anim;
+
+    PluginType pluginType;
+    SubPlugin* activePlugin;
     ANPAudioTrack* track;
-    int32_t mUnichar;
-    
-    bool mTestTimers;
-    uint32_t mStartTime;
-    uint32_t mPrevTime;
-    int      mTimerCount;
+
 } PluginObject;
 
 NPClass *getPluginClass(void);
diff --git a/samples/SampleBrowserPlugin/jni/pluginGraphics.cpp b/samples/BrowserPlugin/jni/animation/AnimationPlugin.cpp
similarity index 78%
rename from samples/SampleBrowserPlugin/jni/pluginGraphics.cpp
rename to samples/BrowserPlugin/jni/animation/AnimationPlugin.cpp
index 7fbf7a7..7f15d0d 100644
--- a/samples/SampleBrowserPlugin/jni/pluginGraphics.cpp
+++ b/samples/BrowserPlugin/jni/animation/AnimationPlugin.cpp
@@ -22,10 +22,9 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
- 
-#include "pluginGraphics.h"
 
-#include "android_npapi.h"
+#include "AnimationPlugin.h"
+
 #include <stdio.h>
 #include <sys/time.h>
 #include <time.h>
@@ -63,6 +62,20 @@
     browser->invalidaterect(instance, &inval);
 }
 
+static void drawPlugin(SubPlugin* plugin, const ANPBitmap& bitmap, const ANPRectI& clip) {
+    ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
+
+    ANPRectF clipR;
+    clipR.left = clip.left;
+    clipR.top = clip.top;
+    clipR.right = clip.right;
+    clipR.bottom = clip.bottom;
+    gCanvasI.clipRect(canvas, &clipR);
+
+    plugin->draw(canvas);
+    gCanvasI.deleteCanvas(canvas);
+}
+
 uint32_t getMSecs() {
     struct timeval tv;
     gettimeofday(&tv, NULL);
@@ -71,38 +84,28 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-class BallAnimation : public Animation {
-public:
-    BallAnimation(NPP inst);
-    virtual ~BallAnimation();
-    virtual void draw(ANPCanvas*);
-private:
-    float m_x;
-    float m_y;
-    float m_dx;
-    float m_dy;
-    
-    ANPRectF    m_oval;
-    ANPPaint*   m_paint;
-    
-    static const float SCALE = 0.1;
-};
-
-BallAnimation::BallAnimation(NPP inst) : Animation(inst) {
+BallAnimation::BallAnimation(NPP inst) : SubPlugin(inst) {
     m_x = m_y = 0;
     m_dx = 7 * SCALE;
     m_dy = 5 * SCALE;
-    
+
     memset(&m_oval, 0, sizeof(m_oval));
 
     m_paint = gPaintI.newPaint();
     gPaintI.setFlags(m_paint, gPaintI.getFlags(m_paint) | kAntiAlias_ANPPaintFlag);
     gPaintI.setColor(m_paint, 0xFFFF0000);
     gPaintI.setTextSize(m_paint, 24);
-    
+
     ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
     gPaintI.setTypeface(m_paint, tf);
     gTypefaceI.unref(tf);
+
+    //register for key and touch events
+    ANPEventFlags flags = kKey_ANPEventFlag | kTouch_ANPEventFlag;
+    NPError err = browser->setvalue(inst, kAcceptEvents_ANPSetValue, &flags);
+    if (err != NPERR_NO_ERROR) {
+        gLogI.log(inst, kError_ANPLogType, "Error selecting input events.");
+    }
 }
 
 BallAnimation::~BallAnimation() {
@@ -166,45 +169,46 @@
 #endif
         gPathI.deletePath(path);
     }
-    
+
     gPaintI.setColor(m_paint, 0xFFFF0000);
     gCanvasI.drawOval(canvas, &m_oval, m_paint);
-    
+
     bounce(&m_x, &m_dx, obj->window->width - OW);
     bounce(&m_y, &m_dy, obj->window->height - OH);
-    
-    if (obj->mUnichar) {
+
+    if (mUnichar) {
         ANPFontMetrics fm;
         gPaintI.getFontMetrics(m_paint, &fm);
-        
+
         gPaintI.setColor(m_paint, 0xFF0000FF);
-        char c = static_cast<char>(obj->mUnichar);
+        char c = static_cast<char>(mUnichar);
         gCanvasI.drawText(canvas, &c, 1, 10, -fm.fTop, m_paint);
     }
 }
 
-///////////////////////////////////////////////////////////////////////////////
+int16 BallAnimation::handleEvent(const ANPEvent* evt) {
+    NPP instance = this->inst();
 
-void drawPlugin(NPP instance, const ANPBitmap& bitmap, const ANPRectI& clip) {
-    ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
-    
-    ANPRectF clipR;
-    clipR.left = clip.left;
-    clipR.top = clip.top;
-    clipR.right = clip.right;
-    clipR.bottom = clip.bottom;
-    gCanvasI.clipRect(canvas, &clipR);
-    
-    drawPlugin(instance, canvas);
-    
-    gCanvasI.deleteCanvas(canvas);
-}
+    switch (evt->eventType) {
+        case kDraw_ANPEventType:
+            switch (evt->data.draw.model) {
+                case kBitmap_ANPDrawingModel:
+                    drawPlugin(this, evt->data.draw.data.bitmap, evt->data.draw.clip);
+                    return 1;
+                default:
+                    break;   // unknown drawing model
+            }
 
-void drawPlugin(NPP instance, ANPCanvas* canvas) {
-    PluginObject *obj = (PluginObject*) instance->pdata;    
-    if (obj->anim == NULL) {
-        obj->anim = new BallAnimation(instance);
+        case kKey_ANPEventType:
+            if (evt->data.key.action == kDown_ANPKeyAction) {
+                mUnichar = evt->data.key.unichar;
+                gLogI.log(instance, kDebug_ANPLogType, "ball downkey event");
+                browser->invalidaterect(instance, NULL);
+            }
+            return 1;
+
+        default:
+            break;
     }
-    obj->anim->draw(canvas);
+    return 0;   // unknown or unhandled event
 }
-
diff --git a/samples/SampleBrowserPlugin/jni/pluginGraphics.h b/samples/BrowserPlugin/jni/animation/AnimationPlugin.h
similarity index 77%
rename from samples/SampleBrowserPlugin/jni/pluginGraphics.h
rename to samples/BrowserPlugin/jni/animation/AnimationPlugin.h
index 4dceb26..1771d79 100644
--- a/samples/SampleBrowserPlugin/jni/pluginGraphics.h
+++ b/samples/BrowserPlugin/jni/animation/AnimationPlugin.h
@@ -22,19 +22,33 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
- 
-#include "main.h" // for NPAPI definitions
+
 #include "PluginObject.h"
+#include "android_npapi.h"
 
 #ifndef pluginGraphics__DEFINED
 #define pluginGraphics__DEFINED
 
-struct ANPBitmap;
-struct ANPCanvas;
-struct ANPRectI;
+class BallAnimation : public SubPlugin {
+public:
+    BallAnimation(NPP inst);
+    virtual ~BallAnimation();
+    virtual void draw(ANPCanvas*);
+    virtual int16 handleEvent(const ANPEvent* evt);
+private:
+    float m_x;
+    float m_y;
+    float m_dx;
+    float m_dy;
 
-void drawPlugin(NPP instance, const ANPBitmap& bitmap, const ANPRectI& clip);
-void drawPlugin(NPP instance, ANPCanvas*);
+    int32_t mUnichar;
+
+    ANPRectF    m_oval;
+    ANPPaint*   m_paint;
+
+    static const float SCALE = 0.1;
+};
+
 uint32_t getMSecs();
 
 #endif // pluginGraphics__DEFINED
diff --git a/samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp b/samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp
new file mode 100644
index 0000000..0fbb421
--- /dev/null
+++ b/samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "BackgroundPlugin.h"
+#include "android_npapi.h"
+
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
+#include <string.h>
+
+extern NPNetscapeFuncs*        browser;
+extern ANPBitmapInterfaceV0    gBitmapI;
+extern ANPLogInterfaceV0       gLogI;
+extern ANPCanvasInterfaceV0    gCanvasI;
+extern ANPPaintInterfaceV0     gPaintI;
+extern ANPPathInterfaceV0      gPathI;
+extern ANPTypefaceInterfaceV0  gTypefaceI;
+
+extern uint32_t getMSecs();
+
+#define ARRAY_COUNT(array)      (sizeof(array) / sizeof(array[0]))
+
+//#define LOG_ERROR(inst, string, params...) gLogI.log(inst, kError_ANPLogType, (log_prefix + string), inst, params)
+
+///////////////////////////////////////////////////////////////////////////////
+
+BackgroundPlugin::BackgroundPlugin(NPP inst) : SubPlugin(inst) {
+
+    m_paint = gPaintI.newPaint();
+    gPaintI.setFlags(m_paint, gPaintI.getFlags(m_paint) | kAntiAlias_ANPPaintFlag);
+    gPaintI.setColor(m_paint, 0xFFFF0000);
+    gPaintI.setTextSize(m_paint, 16);
+
+    ANPTypeface* tf = gTypefaceI.createFromName("serif", kItalic_ANPTypefaceStyle);
+    gPaintI.setTypeface(m_paint, tf);
+    gTypefaceI.unref(tf);
+
+    //initialize variables
+    mFinishedStageOne   = false;
+    mFinishedStageTwo   = false;
+    mFinishedStageThree = false;
+
+    // test basic plugin functionality
+    test_logging(); // android logging
+    test_timers();  // plugin timers
+    test_bitmaps(); // android bitmaps
+}
+
+BackgroundPlugin::~BackgroundPlugin() {
+}
+
+void BackgroundPlugin::draw(ANPCanvas* canvas) {
+
+    gCanvasI.drawColor(canvas, 0xFFFFFFFF);
+
+    ANPFontMetrics fm;
+    gPaintI.getFontMetrics(m_paint, &fm);
+
+    gPaintI.setColor(m_paint, 0xFF0000FF);
+    const char c[] = "This is a background plugin.";
+    gCanvasI.drawText(canvas, c, sizeof(c)-1, 10, -fm.fTop, m_paint);
+}
+
+static void drawPlugin(SubPlugin* plugin, const ANPBitmap& bitmap, const ANPRectI& clip) {
+
+   ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
+
+    ANPRectF clipR;
+    clipR.left = clip.left;
+    clipR.top = clip.top;
+    clipR.right = clip.right;
+    clipR.bottom = clip.bottom;
+    gCanvasI.clipRect(canvas, &clipR);
+
+    plugin->draw(canvas);
+    gCanvasI.deleteCanvas(canvas);
+}
+
+int16 BackgroundPlugin::handleEvent(const ANPEvent* evt) {
+    NPP instance = this->inst();
+
+    switch (evt->eventType) {
+        case kDraw_ANPEventType:
+            switch (evt->data.draw.model) {
+                case kBitmap_ANPDrawingModel:
+                    test_bitmap_transparency(evt);
+                    drawPlugin(this, evt->data.draw.data.bitmap, evt->data.draw.clip);
+                    return 1;
+                default:
+                    break;   // unknown drawing model
+            }
+        case kTouch_ANPEventType:
+            gLogI.log(instance, kError_ANPLogType, " ------ %p the plugin did not request touch events", instance);
+        case kKey_ANPEventType:
+            gLogI.log(instance, kError_ANPLogType, " ------ %p the plugin did not request key events", instance);
+        default:
+            break;
+    }
+    return 0;   // unknown or unhandled event
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// LOGGING TESTS
+///////////////////////////////////////////////////////////////////////////////
+
+
+void BackgroundPlugin::test_logging() {
+    NPP instance = this->inst();
+
+    //LOG_ERROR(instance, " ------ %p Testing Log Error", instance);
+    gLogI.log(instance, kError_ANPLogType, " ------ %p Testing Log Error", instance);
+    gLogI.log(instance, kWarning_ANPLogType, " ------ %p Testing Log Warning", instance);
+    gLogI.log(instance, kDebug_ANPLogType, " ------ %p Testing Log Debug", instance);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TIMER TESTS
+///////////////////////////////////////////////////////////////////////////////
+
+#define TIMER_INTERVAL     50
+static void timer_oneshot(NPP instance, uint32 timerID);
+static void timer_repeat(NPP instance, uint32 timerID);
+static void timer_neverfires(NPP instance, uint32 timerID);
+static void timer_latency(NPP instance, uint32 timerID);
+
+void BackgroundPlugin::test_timers() {
+    NPP instance = this->inst();
+
+    //Setup the testing counters
+    mTimerRepeatCount = 5;
+    mTimerLatencyCount = 5;
+
+    // test for bogus timerID
+    browser->unscheduletimer(instance, 999999);
+    // test one-shot
+    browser->scheduletimer(instance, 100, false, timer_oneshot);
+    // test repeat
+    browser->scheduletimer(instance, 50, true, timer_repeat);
+    // test timer latency
+    browser->scheduletimer(instance, TIMER_INTERVAL, true, timer_latency);
+    mStartTime = mPrevTime = getMSecs();
+    // test unschedule immediately
+    uint32 id = browser->scheduletimer(instance, 100, false, timer_neverfires);
+    browser->unscheduletimer(instance, id);
+    // test double unschedule (should be no-op)
+    browser->unscheduletimer(instance, id);
+
+}
+
+static void timer_oneshot(NPP instance, uint32 timerID) {
+    gLogI.log(instance, kDebug_ANPLogType, "-------- oneshot timer\n");
+}
+
+static void timer_repeat(NPP instance, uint32 timerID) {
+    BackgroundPlugin *obj = ((BackgroundPlugin*) ((PluginObject*) instance->pdata)->activePlugin);
+
+    gLogI.log(instance, kDebug_ANPLogType, "-------- repeat timer %d\n",
+              obj->mTimerRepeatCount);
+    if (--obj->mTimerRepeatCount == 0) {
+        browser->unscheduletimer(instance, timerID);
+    }
+}
+
+static void timer_neverfires(NPP instance, uint32 timerID) {
+    gLogI.log(instance, kError_ANPLogType, "-------- timer_neverfires!!!\n");
+}
+
+static void timer_latency(NPP instance, uint32 timerID) {
+    BackgroundPlugin *obj = ((BackgroundPlugin*) ((PluginObject*) instance->pdata)->activePlugin);
+
+    obj->mTimerLatencyCurrentCount += 1;
+
+    uint32_t now = getMSecs();
+    uint32_t interval = now - obj->mPrevTime;
+    uint32_t dur = now - obj->mStartTime;
+    uint32_t expectedDur = obj->mTimerLatencyCurrentCount * TIMER_INTERVAL;
+    int32_t drift = dur - expectedDur;
+    int32_t avgDrift = drift / obj->mTimerLatencyCurrentCount;
+
+    obj->mPrevTime = now;
+
+    gLogI.log(instance, kDebug_ANPLogType,
+              "-------- latency test: [%3d] interval %d expected %d, total %d expected %d, drift %d avg %d\n",
+              obj->mTimerLatencyCurrentCount, interval, TIMER_INTERVAL, dur,
+              expectedDur, drift, avgDrift);
+
+    if (--obj->mTimerLatencyCount == 0) {
+        browser->unscheduletimer(instance, timerID);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BITMAP TESTS
+///////////////////////////////////////////////////////////////////////////////
+
+static void test_formats(NPP instance);
+
+void BackgroundPlugin::test_bitmaps() {
+    test_formats(this->inst());
+}
+
+static void test_formats(NPP instance) {
+
+    // TODO pull names from enum in npapi instead of hardcoding them
+    static const struct {
+        ANPBitmapFormat fFormat;
+        const char*     fName;
+    } gRecs[] = {
+        { kUnknown_ANPBitmapFormat,   "unknown" },
+        { kRGBA_8888_ANPBitmapFormat, "8888" },
+        { kRGB_565_ANPBitmapFormat,   "565" },
+    };
+
+    ANPPixelPacking packing;
+    for (size_t i = 0; i < ARRAY_COUNT(gRecs); i++) {
+        if (gBitmapI.getPixelPacking(gRecs[i].fFormat, &packing)) {
+            gLogI.log(instance, kDebug_ANPLogType,
+                      "pixel format [%d] %s has packing ARGB [%d %d] [%d %d] [%d %d] [%d %d]\n",
+                      gRecs[i].fFormat, gRecs[i].fName,
+                      packing.AShift, packing.ABits,
+                      packing.RShift, packing.RBits,
+                      packing.GShift, packing.GBits,
+                      packing.BShift, packing.BBits);
+        } else {
+            gLogI.log(instance, kDebug_ANPLogType,
+                      "pixel format [%d] %s has no packing\n",
+                      gRecs[i].fFormat, gRecs[i].fName);
+        }
+    }
+}
+
+void BackgroundPlugin::test_bitmap_transparency(const ANPEvent* evt) {
+    NPP instance = this->inst();
+
+    // check default & set transparent
+    if (!mFinishedStageOne) {
+
+        gLogI.log(instance, kDebug_ANPLogType, "BEGIN: testing bitmap transparency");
+
+        //check to make sure it is not transparent
+        if (evt->data.draw.data.bitmap.format == kRGBA_8888_ANPBitmapFormat) {
+            gLogI.log(instance, kError_ANPLogType, "bitmap default format is transparent");
+        }
+
+        //make it transparent (any non-null value will set it to true)
+        bool value = true;
+        NPError err = browser->setvalue(instance, NPPVpluginTransparentBool, &value);
+        if (err != NPERR_NO_ERROR) {
+            gLogI.log(instance, kError_ANPLogType, "Error setting transparency.");
+        }
+
+        mFinishedStageOne = true;
+        browser->invalidaterect(instance, NULL);
+    }
+    // check transparent & set opaque
+    else if (!mFinishedStageTwo) {
+
+        //check to make sure it is transparent
+        if (evt->data.draw.data.bitmap.format != kRGBA_8888_ANPBitmapFormat) {
+            gLogI.log(instance, kError_ANPLogType, "bitmap did not change to transparent format");
+        }
+
+        //make it opaque
+        NPError err = browser->setvalue(instance, NPPVpluginTransparentBool, NULL);
+        if (err != NPERR_NO_ERROR) {
+            gLogI.log(instance, kError_ANPLogType, "Error setting transparency.");
+        }
+
+        mFinishedStageTwo = true;
+    }
+    // check opaque
+    else if (!mFinishedStageThree) {
+
+        //check to make sure it is not transparent
+        if (evt->data.draw.data.bitmap.format == kRGBA_8888_ANPBitmapFormat) {
+            gLogI.log(instance, kError_ANPLogType, "bitmap default format is transparent");
+        }
+
+        gLogI.log(instance, kDebug_ANPLogType, "END: testing bitmap transparency");
+
+        mFinishedStageThree = true;
+    }
+}
diff --git a/samples/BrowserPlugin/jni/background/BackgroundPlugin.h b/samples/BrowserPlugin/jni/background/BackgroundPlugin.h
new file mode 100644
index 0000000..4e74fce
--- /dev/null
+++ b/samples/BrowserPlugin/jni/background/BackgroundPlugin.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PluginObject.h"
+
+#ifndef backgroundPlugin__DEFINED
+#define backgroundPlugin__DEFINED
+
+struct ANPCanvas;
+struct ANPEvent;
+struct ANPPaint;
+
+class BackgroundPlugin : public SubPlugin {
+public:
+    BackgroundPlugin(NPP inst);
+    virtual ~BackgroundPlugin();
+    virtual void draw(ANPCanvas*);
+    virtual int16 handleEvent(const ANPEvent* evt);
+
+    // Timer Testing Variables
+    uint32_t mStartTime;
+    uint32_t mPrevTime;
+    int      mTimerRepeatCount;
+    int      mTimerLatencyCount;
+    int      mTimerLatencyCurrentCount;
+
+    // Bitmap Transparency Variables
+    bool mFinishedStageOne;   // check default & set transparent
+    bool mFinishedStageTwo;   // check transparent & set opaque
+    bool mFinishedStageThree; // check opaque
+
+private:
+
+    ANPPaint*   m_paint;
+
+    void test_logging();
+    void test_timers();
+    void test_bitmaps();
+    void test_bitmap_transparency(const ANPEvent* evt);
+
+};
+
+#endif // backgroundPlugin__DEFINED
diff --git a/samples/SampleBrowserPlugin/jni/main.cpp b/samples/BrowserPlugin/jni/main.cpp
similarity index 71%
rename from samples/SampleBrowserPlugin/jni/main.cpp
rename to samples/BrowserPlugin/jni/main.cpp
index 82d29b6..e2fb6d6 100644
--- a/samples/SampleBrowserPlugin/jni/main.cpp
+++ b/samples/BrowserPlugin/jni/main.cpp
@@ -28,7 +28,8 @@
 #include <stdio.h>
 #include "main.h"
 #include "PluginObject.h"
-#include "pluginGraphics.h"
+#include "AnimationPlugin.h"
+#include "BackgroundPlugin.h"
 #include "android_npapi.h"
 
 NPNetscapeFuncs* browser;
@@ -128,103 +129,86 @@
 
 const char *NP_GetMIMEDescription(void)
 {
-    return "application/x-testplugin:tst:Test plugin mimetype is application/x-testplugin";
+    return "application/x-testbrowserplugin:tst:Test plugin mimetype is application/x-testbrowserplugin";
 }
 
 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
                 char* argn[], char* argv[], NPSavedData* saved)
 {
+
+    /* BEGIN: STANDARD PLUGIN FRAMEWORK */
     PluginObject *obj = NULL;
 
     // Scripting functions appeared in NPAPI version 14
     if (browser->version >= 14) {
-        instance->pdata = browser->createobject (instance, getPluginClass());
-        obj = static_cast<PluginObject*>(instance->pdata);
-        bzero(obj, sizeof(*obj));
+    instance->pdata = browser->createobject (instance, getPluginClass());
+    obj = static_cast<PluginObject*>(instance->pdata);
+    bzero(obj, sizeof(*obj));
     }
+    /* END: STANDARD PLUGIN FRAMEWORK */
 
-    uint32_t bits;
-    NPError err = browser->getvalue(instance, kSupportedDrawingModel_ANPGetValue, &bits);
-    if (err) {
-        gLogI.log(instance, kError_ANPLogType, "supported model err %d", err);
-        return err;
-    }
-
+    // select the drawing model based on user input
     ANPDrawingModel model = kBitmap_ANPDrawingModel;
 
-    int count = argc;
-    for (int i = 0; i < count; i++) {
+    for (int i = 0; i < argc; i++) {
         if (!strcmp(argn[i], "DrawingModel")) {
             if (!strcmp(argv[i], "Bitmap")) {
                 model = kBitmap_ANPDrawingModel;
             }
             if (!strcmp(argv[i], "Canvas")) {
-            //    obj->mTestTimers = true;
+                //TODO support drawing on canvas instead of bitmap
             }
             gLogI.log(instance, kDebug_ANPLogType, "------ %p DrawingModel is %d", instance, model);
             break;
         }
     }
 
-    // comment this out to draw via bitmaps (the default)
-    err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue,
+    // comment this out to use the default model (bitmaps)
+    NPError err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue,
                             reinterpret_cast<void*>(model));
     if (err) {
         gLogI.log(instance, kError_ANPLogType, "request model %d err %d", model, err);
+        return err;
     }
-    return err;
+
+    // select the pluginType
+    for (int i = 0; i < argc; i++) {
+        if (!strcmp(argn[i], "PluginType")) {
+            if (!strcmp(argv[i], "Animation")) {
+                obj->pluginType = kAnimation_PluginType;
+                obj->activePlugin = new BallAnimation(instance);
+            }
+            else if (!strcmp(argv[i], "Audio")) {
+                obj->pluginType = kAudio_PluginType;
+                //TODO add audio here
+            }
+            else if (!strcmp(argv[i], "Background")) {
+                obj->pluginType = kBackground_PluginType;
+                obj->activePlugin = new BackgroundPlugin(instance);
+            }
+            gLogI.log(instance, kDebug_ANPLogType, "------ %p PluginType is %d", instance, obj->pluginType);
+            break;
+        }
+    }
+
+    // if no pluginType is specified then default to Animation
+    if (!obj->pluginType) {
+        obj->pluginType = kAnimation_PluginType;
+        obj->activePlugin = new BallAnimation(instance);
+    }
+
+    return NPERR_NO_ERROR;
 }
 
 NPError NPP_Destroy(NPP instance, NPSavedData** save)
 {
     PluginObject *obj = (PluginObject*) instance->pdata;
-    delete obj->anim;
+    delete obj->activePlugin;
     gSoundI.deleteTrack(obj->track);
 
     return NPERR_NO_ERROR;
 }
 
-static void timer_oneshot(NPP instance, uint32 timerID) {
-    gLogI.log(instance, kDebug_ANPLogType, "-------- oneshot timer\n");
-}
-
-static int gTimerRepeatCount;
-static void timer_repeat(NPP instance, uint32 timerID) {
-
-    gLogI.log(instance, kDebug_ANPLogType, "-------- repeat timer %d\n",
-              gTimerRepeatCount);
-    if (--gTimerRepeatCount == 0) {
-        browser->unscheduletimer(instance, timerID);
-    }
-}
-
-static void timer_neverfires(NPP instance, uint32 timerID) {
-    gLogI.log(instance, kError_ANPLogType, "-------- timer_neverfires!!!\n");
-}
-
-#define TIMER_INTERVAL     50
-
-static void timer_latency(NPP instance, uint32 timerID) {
-    PluginObject *obj = (PluginObject*) instance->pdata;
-
-    obj->mTimerCount += 1;
-
-    uint32_t now = getMSecs();
-    uint32_t interval = now - obj->mPrevTime;
-
-    uint32_t dur = now - obj->mStartTime;
-    uint32_t expectedDur = obj->mTimerCount * TIMER_INTERVAL;
-    int32_t drift = dur - expectedDur;
-    int32_t aveDrift = drift / obj->mTimerCount;
-
-    obj->mPrevTime = now;
-
-    gLogI.log(instance, kDebug_ANPLogType,
-              "-------- latency test: [%3d] interval %d expected %d, total %d expected %d, drift %d ave %d\n",
-              obj->mTimerCount, interval, TIMER_INTERVAL, dur, expectedDur,
-              drift, aveDrift);
-}
-
 NPError NPP_SetWindow(NPP instance, NPWindow* window)
 {
     PluginObject *obj = (PluginObject*) instance->pdata;
@@ -234,63 +218,11 @@
         obj->window = window;
     }
 
-    static bool gTestTimers;
-    if (!gTestTimers) {
-        gTestTimers = true;
-        // test for bogus timerID
-        browser->unscheduletimer(instance, 999999);
-        // test oneshot
-        browser->scheduletimer(instance, 100, false, timer_oneshot);
-        // test repeat
-        gTimerRepeatCount = 10;
-        browser->scheduletimer(instance, 50, true, timer_repeat);
-        // test unschedule immediately
-        uint32 id = browser->scheduletimer(instance, 100, false, timer_neverfires);
-        browser->unscheduletimer(instance, id);
-        // test double unschedlue (should be no-op)
-        browser->unscheduletimer(instance, id);
-    }
-
-    if (obj->mTestTimers) {
-        browser->scheduletimer(instance, TIMER_INTERVAL, true, timer_latency);
-        obj->mStartTime = obj->mPrevTime = getMSecs();
-        obj->mTestTimers = false;
-    }
-
-    if (true) {
-        static const struct {
-            ANPBitmapFormat fFormat;
-            const char*     fName;
-        } gRecs[] = {
-            { kUnknown_ANPBitmapFormat,   "unknown" },
-            { kRGBA_8888_ANPBitmapFormat, "8888" },
-            { kRGB_565_ANPBitmapFormat,   "565" },
-        };
-
-        ANPPixelPacking packing;
-        for (size_t i = 0; i < ARRAY_COUNT(gRecs); i++) {
-            if (gBitmapI.getPixelPacking(gRecs[i].fFormat, &packing)) {
-                gLogI.log(instance, kDebug_ANPLogType,
-                          "pixel format [%d] %s has packing ARGB [%d %d] [%d %d] [%d %d] [%d %d]\n",
-                          gRecs[i].fFormat, gRecs[i].fName,
-                          packing.AShift, packing.ABits,
-                          packing.RShift, packing.RBits,
-                          packing.GShift, packing.GBits,
-                          packing.BShift, packing.BBits);
-            } else {
-                gLogI.log(instance, kDebug_ANPLogType,
-                          "pixel format [%d] %s has no packing\n",
-                          gRecs[i].fFormat, gRecs[i].fName);
-            }
-        }
-    }
-
     browser->invalidaterect(instance, NULL);
 
     return NPERR_NO_ERROR;
 }
 
-
 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
 {
     *stype = NP_ASFILEONLY;
@@ -318,7 +250,6 @@
 
 void NPP_Print(NPP instance, NPPrint* platformPrint)
 {
-
 }
 
 struct SoundPlay {
@@ -370,14 +301,22 @@
 
     switch (evt->eventType) {
         case kDraw_ANPEventType:
-            switch (evt->data.draw.model) {
-                case kBitmap_ANPDrawingModel:
-                    drawPlugin(instance, evt->data.draw.data.bitmap,
-                               evt->data.draw.clip);
-                    return 1;
-                default:
-                    break;   // unknown drawing model
+
+            if (evt->data.draw.model == kBitmap_ANPDrawingModel) {
+
+                static ANPBitmapFormat currentFormat = -1;
+                if (evt->data.draw.data.bitmap.format != currentFormat) {
+                    currentFormat = evt->data.draw.data.bitmap.format;
+                    gLogI.log(instance, kDebug_ANPLogType, "---- %p Draw (bitmap)"
+                              " clip=%d,%d,%d,%d format=%d", instance,
+                              evt->data.draw.clip.left,
+                              evt->data.draw.clip.top,
+                              evt->data.draw.clip.right,
+                              evt->data.draw.clip.bottom,
+                              evt->data.draw.data.bitmap.format);
+                }
             }
+            break;
 
         case kKey_ANPEventType:
             gLogI.log(instance, kDebug_ANPLogType, "---- %p Key action=%d"
@@ -388,18 +327,14 @@
                       evt->data.key.unichar,
                       evt->data.key.repeatCount,
                       evt->data.key.modifiers);
-            if (evt->data.key.action == kDown_ANPKeyAction) {
-                obj->mUnichar = evt->data.key.unichar;
-                browser->invalidaterect(instance, NULL);
-            }
-            return 1;
+            break;
 
         case kLifecycle_ANPEventType:
             gLogI.log(instance, kDebug_ANPLogType, "---- %p Lifecycle action=%d",
-                      instance, evt->data.lifecycle.action);
+                                instance, evt->data.lifecycle.action);
             break;
 
-        case kTouch_ANPEventType:
+       case kTouch_ANPEventType:
             gLogI.log(instance, kDebug_ANPLogType, "---- %p Touch action=%d [%d %d]",
                       instance, evt->data.touch.action, evt->data.touch.x,
                       evt->data.touch.y);
@@ -422,7 +357,14 @@
         default:
             break;
     }
-    return 0;   // unknown or unhandled event
+
+    if(!obj->activePlugin) {
+        gLogI.log(instance, kError_ANPLogType, "the active plugin is null.");
+        return 0; // unknown or unhandled event
+    }
+    else {
+        return obj->activePlugin->handleEvent(evt);
+    }
 }
 
 void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
diff --git a/samples/SampleBrowserPlugin/jni/main.h b/samples/BrowserPlugin/jni/main.h
similarity index 100%
rename from samples/SampleBrowserPlugin/jni/main.h
rename to samples/BrowserPlugin/jni/main.h
diff --git a/samples/SampleBrowserPlugin/res/drawable/sample_browser_plugin.png b/samples/BrowserPlugin/res/drawable/sample_browser_plugin.png
similarity index 100%
rename from samples/SampleBrowserPlugin/res/drawable/sample_browser_plugin.png
rename to samples/BrowserPlugin/res/drawable/sample_browser_plugin.png
Binary files differ
diff --git a/samples/SampleBrowserPlugin/res/values/strings.xml b/samples/BrowserPlugin/res/values/strings.xml
similarity index 100%
rename from samples/SampleBrowserPlugin/res/values/strings.xml
rename to samples/BrowserPlugin/res/values/strings.xml
diff --git a/samples/SampleBrowserPlugin/src/com/android/sampleplugin/SamplePlugin.java b/samples/BrowserPlugin/src/com/android/sampleplugin/SamplePlugin.java
similarity index 100%
rename from samples/SampleBrowserPlugin/src/com/android/sampleplugin/SamplePlugin.java
rename to samples/BrowserPlugin/src/com/android/sampleplugin/SamplePlugin.java