diff --git a/samples/BrowserPlugin/jni/Android.mk b/samples/BrowserPlugin/jni/Android.mk index f296a1d73..b888d5405 100644 --- a/samples/BrowserPlugin/jni/Android.mk +++ b/samples/BrowserPlugin/jni/Android.mk @@ -35,7 +35,7 @@ LOCAL_SRC_FILES := \ background/BackgroundPlugin.cpp \ form/FormPlugin.cpp \ paint/PaintPlugin.cpp \ - hello-jni.cpp \ + jni-bridge.cpp \ LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ diff --git a/samples/BrowserPlugin/jni/PluginObject.h b/samples/BrowserPlugin/jni/PluginObject.h index 82f6f4814..61486d599 100644 --- a/samples/BrowserPlugin/jni/PluginObject.h +++ b/samples/BrowserPlugin/jni/PluginObject.h @@ -35,6 +35,7 @@ #define PluginObject__DEFINED #include "main.h" +#include class SubPlugin { public: @@ -49,6 +50,16 @@ private: NPP m_inst; }; +class SurfaceSubPlugin : public SubPlugin { +public: + SurfaceSubPlugin(NPP inst) : SubPlugin(inst) {} + virtual ~SurfaceSubPlugin() {} + virtual bool isFixedSurface() = 0; + virtual void surfaceCreated(JNIEnv*, jobject) = 0; + virtual void surfaceChanged(int format, int width, int height) = 0; + virtual void surfaceDestroyed() = 0; +}; + enum PluginTypes { kAnimation_PluginType = 1, kAudio_PluginType = 2, diff --git a/samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp b/samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp index eac5db211..2a65b4f60 100644 --- a/samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp +++ b/samples/BrowserPlugin/jni/background/BackgroundPlugin.cpp @@ -50,13 +50,11 @@ static uint32_t getMSecs() { /////////////////////////////////////////////////////////////////////////////// -BackgroundPlugin::BackgroundPlugin(NPP inst) : SubPlugin(inst) { +BackgroundPlugin::BackgroundPlugin(NPP inst) : SurfaceSubPlugin(inst) { // initialize the drawing surface - m_surfaceReady = false; - m_surface = gSurfaceI.newRasterSurface(inst, kRGB_565_ANPBitmapFormat, false); - if(!m_surface) - gLogI.log(inst, kError_ANPLogType, "----%p Unable to create RGBA surface", inst); + m_surface = NULL; + m_vm = NULL; //initialize bitmap transparency variables mFinishedStageOne = false; @@ -71,14 +69,33 @@ BackgroundPlugin::BackgroundPlugin(NPP inst) : SubPlugin(inst) { test_javascript(); } -BackgroundPlugin::~BackgroundPlugin() { - gSurfaceI.deleteSurface(m_surface); -} +BackgroundPlugin::~BackgroundPlugin() { } bool BackgroundPlugin::supportsDrawingModel(ANPDrawingModel model) { return (model == kSurface_ANPDrawingModel); } +bool BackgroundPlugin::isFixedSurface() { + return false; +} + +void BackgroundPlugin::surfaceCreated(JNIEnv* env, jobject surface) { + env->GetJavaVM(&m_vm); + m_surface = env->NewGlobalRef(surface); +} + +void BackgroundPlugin::surfaceChanged(int format, int width, int height) { + drawPlugin(width, height); +} + +void BackgroundPlugin::surfaceDestroyed() { + JNIEnv* env = NULL; + if (m_surface && m_vm->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { + env->DeleteGlobalRef(m_surface); + m_surface = NULL; + } +} + void BackgroundPlugin::drawPlugin(int surfaceWidth, int surfaceHeight) { // get the plugin's dimensions according to the DOM @@ -101,7 +118,9 @@ void BackgroundPlugin::drawPlugin(int surfaceWidth, int surfaceHeight) { // lock the surface ANPBitmap bitmap; - if (!m_surfaceReady || !gSurfaceI.lock(m_surface, &bitmap, NULL)) { + JNIEnv* env = NULL; + if (!m_surface || m_vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK || + !gSurfaceI.lock(env, m_surface, &bitmap, NULL)) { gLogI.log(inst(), kError_ANPLogType, " ------ %p unable to lock the plugin", inst()); return; } @@ -129,7 +148,7 @@ void BackgroundPlugin::drawPlugin(int surfaceWidth, int surfaceHeight) { // clean up variables and unlock the surface gPaintI.deletePaint(paint); gCanvasI.deleteCanvas(canvas); - gSurfaceI.unlock(m_surface); + gSurfaceI.unlock(env, m_surface); } int16 BackgroundPlugin::handleEvent(const ANPEvent* evt) { @@ -137,20 +156,6 @@ int16 BackgroundPlugin::handleEvent(const ANPEvent* evt) { case kDraw_ANPEventType: gLogI.log(inst(), kError_ANPLogType, " ------ %p the plugin did not request draw events", inst()); break; - case kSurface_ANPEventType: - switch (evt->data.surface.action) { - case kCreated_ANPSurfaceAction: - m_surfaceReady = true; - return 1; - case kDestroyed_ANPSurfaceAction: - m_surfaceReady = false; - return 1; - case kChanged_ANPSurfaceAction: - drawPlugin(evt->data.surface.data.changed.width, - evt->data.surface.data.changed.height); - return 1; - } - break; case kLifecycle_ANPEventType: if (evt->data.lifecycle.action == kOnLoad_ANPLifecycleAction) { gLogI.log(inst(), kDebug_ANPLogType, " ------ %p the plugin received an onLoad event", inst()); diff --git a/samples/BrowserPlugin/jni/background/BackgroundPlugin.h b/samples/BrowserPlugin/jni/background/BackgroundPlugin.h index ed428b5ce..3b9c7baff 100644 --- a/samples/BrowserPlugin/jni/background/BackgroundPlugin.h +++ b/samples/BrowserPlugin/jni/background/BackgroundPlugin.h @@ -28,12 +28,16 @@ #ifndef backgroundPlugin__DEFINED #define backgroundPlugin__DEFINED -class BackgroundPlugin : public SubPlugin { +class BackgroundPlugin : public SurfaceSubPlugin { public: BackgroundPlugin(NPP inst); virtual ~BackgroundPlugin(); virtual bool supportsDrawingModel(ANPDrawingModel); virtual int16 handleEvent(const ANPEvent* evt); + virtual void surfaceCreated(JNIEnv* env, jobject surface); + virtual void surfaceChanged(int format, int width, int height); + virtual void surfaceDestroyed(); + virtual bool isFixedSurface(); // Timer Testing Variables uint32_t mStartTime; @@ -50,8 +54,8 @@ public: private: void drawPlugin(int surfaceWidth, int surfaceHeight); - bool m_surfaceReady; - ANPSurface* m_surface; + jobject m_surface; + JavaVM* m_vm; void test_logging(); void test_timers(); diff --git a/samples/BrowserPlugin/jni/jni-bridge.cpp b/samples/BrowserPlugin/jni/jni-bridge.cpp new file mode 100644 index 000000000..45ecd544c --- /dev/null +++ b/samples/BrowserPlugin/jni/jni-bridge.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include +#include +#include +#include + +#include "PluginObject.h" + +#define EXPORT __attribute__((visibility("default"))) + +static SurfaceSubPlugin* getPluginObject(int npp) { + NPP instance = (NPP)npp; + PluginObject* obj = static_cast(instance->pdata); + if (obj && obj->activePlugin + && obj->activePlugin->supportsDrawingModel(kSurface_ANPDrawingModel)) { + return static_cast(obj->activePlugin); + } + return NULL; +} + +static void surfaceCreated(JNIEnv* env, jobject thiz, jint npp, jobject surface) { + SurfaceSubPlugin* obj = getPluginObject(npp); + + //TODO why is this VM different from the one in NP_INIT... + JavaVM* vm = NULL; + env->GetJavaVM(&vm); + + obj->surfaceCreated(env, surface); +} + +static void surfaceChanged(JNIEnv* env, jobject thiz, jint npp, jint format, jint width, jint height) { + SurfaceSubPlugin* obj = getPluginObject(npp); + obj->surfaceChanged(format, width, height); +} + +static void surfaceDestroyed(JNIEnv* env, jobject thiz, jint npp) { + SurfaceSubPlugin* obj = getPluginObject(npp); + if (obj) { + obj->surfaceDestroyed(); + } +} + +static jboolean isFixedSurface(JNIEnv* env, jobject thiz, jint npp) { + SurfaceSubPlugin* obj = getPluginObject(npp); + return obj->isFixedSurface(); +} + +/* + * JNI registration. + */ +static JNINativeMethod gJavaSamplePluginStubMethods[] = { + { "nativeSurfaceCreated", "(ILandroid/view/View;)V", (void*) surfaceCreated }, + { "nativeSurfaceChanged", "(IIII)V", (void*) surfaceChanged }, + { "nativeSurfaceDestroyed", "(I)V", (void*) surfaceDestroyed }, + { "nativeIsFixedSurface", "(I)Z", (void*) isFixedSurface }, +}; + +EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + + JNIEnv* env = NULL; + + if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { + return -1; + } + + jniRegisterNativeMethods(env, "com/android/sampleplugin/SamplePluginStub", + gJavaSamplePluginStubMethods, NELEM(gJavaSamplePluginStubMethods)); + + return JNI_VERSION_1_4; +} diff --git a/samples/BrowserPlugin/jni/main.cpp b/samples/BrowserPlugin/jni/main.cpp index b5aea95ad..7f7496ba2 100644 --- a/samples/BrowserPlugin/jni/main.cpp +++ b/samples/BrowserPlugin/jni/main.cpp @@ -33,7 +33,6 @@ #include "BackgroundPlugin.h" #include "FormPlugin.h" #include "PaintPlugin.h" -#include "android_npapi.h" NPNetscapeFuncs* browser; #define EXPORT __attribute__((visibility("default"))) @@ -173,6 +172,15 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, } } + // notify the plugin API of the location of the java interface + char* className = "com.android.sampleplugin.SamplePluginStub"; + NPError npErr = browser->setvalue(instance, kSetJavaClassName_ANPSetValue, + reinterpret_cast(className)); + if (npErr) { + gLogI.log(instance, kError_ANPLogType, "set class err %d", npErr); + return npErr; + } + // notify the plugin API of the drawing model we wish to use. This must be // done prior to creating certain subPlugin objects (e.g. surfaceViews) NPError err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue, diff --git a/samples/BrowserPlugin/jni/main.h b/samples/BrowserPlugin/jni/main.h index 4532911d9..8ad2cce9b 100644 --- a/samples/BrowserPlugin/jni/main.h +++ b/samples/BrowserPlugin/jni/main.h @@ -27,5 +27,6 @@ #include #include #include "android_npapi.h" +#include "ANPSurface_npapi.h" extern NPNetscapeFuncs* browser; diff --git a/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp b/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp index a34870fb7..5b00dbaed 100644 --- a/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp +++ b/samples/BrowserPlugin/jni/paint/PaintPlugin.cpp @@ -39,7 +39,7 @@ extern ANPTypefaceInterfaceV0 gTypefaceI; /////////////////////////////////////////////////////////////////////////////// -PaintPlugin::PaintPlugin(NPP inst) : SubPlugin(inst) { +PaintPlugin::PaintPlugin(NPP inst) : SurfaceSubPlugin(inst) { m_isTouchActive = false; m_isTouchCurrentInput = true; @@ -51,10 +51,8 @@ PaintPlugin::PaintPlugin(NPP inst) : SubPlugin(inst) { memset(&m_clearSurface, 0, sizeof(m_clearSurface)); // initialize the drawing surface - m_surfaceReady = false; - m_surface = gSurfaceI.newRasterSurface(inst, kRGBA_8888_ANPBitmapFormat, true); - if(!m_surface) - gLogI.log(inst, kError_ANPLogType, "----%p Unable to create RGBA surface", inst); + m_surface = NULL; + m_vm = NULL; // initialize the path m_touchPath = gPathI.newPath(); @@ -85,10 +83,10 @@ PaintPlugin::PaintPlugin(NPP inst) : SubPlugin(inst) { } PaintPlugin::~PaintPlugin() { - gSurfaceI.deleteSurface(m_surface); gPathI.deletePath(m_touchPath); gPaintI.deletePaint(m_paintSurface); gPaintI.deletePaint(m_paintButton); + surfaceDestroyed(); } bool PaintPlugin::supportsDrawingModel(ANPDrawingModel model) { @@ -98,8 +96,11 @@ bool PaintPlugin::supportsDrawingModel(ANPDrawingModel model) { ANPCanvas* PaintPlugin::getCanvas(ANPRectI* dirtyRect) { ANPBitmap bitmap; - if (!m_surfaceReady || !gSurfaceI.lock(m_surface, &bitmap, dirtyRect)) - return NULL; + JNIEnv* env = NULL; + if (!m_surface || m_vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK || + !gSurfaceI.lock(env, m_surface, &bitmap, dirtyRect)) { + return NULL; + } ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap); @@ -130,7 +131,10 @@ ANPCanvas* PaintPlugin::getCanvas(ANPRectF* dirtyRect) { } void PaintPlugin::releaseCanvas(ANPCanvas* canvas) { - gSurfaceI.unlock(m_surface); + JNIEnv* env = NULL; + if (m_surface && m_vm->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { + gSurfaceI.unlock(env, m_surface); + } gCanvasI.deleteCanvas(canvas); } @@ -208,33 +212,37 @@ const char* PaintPlugin::getColorText() { return "Red"; } +bool PaintPlugin::isFixedSurface() { + return true; +} + +void PaintPlugin::surfaceCreated(JNIEnv* env, jobject surface) { + env->GetJavaVM(&m_vm); + m_surface = env->NewGlobalRef(surface); + drawCleanPlugin(); +} + +void PaintPlugin::surfaceChanged(int format, int width, int height) { + // get the plugin's dimensions according to the DOM + PluginObject *obj = (PluginObject*) inst()->pdata; + const int pW = obj->window->width; + const int pH = obj->window->height; + // compare to the plugin's surface dimensions + if (pW != width || pH != height) + gLogI.log(inst(), kError_ANPLogType, + "----%p Invalid Surface Dimensions (%d,%d):(%d,%d)", + inst(), pW, pH, width, height); +} +void PaintPlugin::surfaceDestroyed() { + JNIEnv* env = NULL; + if (m_surface && m_vm->GetEnv((void**) &env, JNI_VERSION_1_4) == JNI_OK) { + env->DeleteGlobalRef(m_surface); + m_surface = NULL; + } +} + int16 PaintPlugin::handleEvent(const ANPEvent* evt) { switch (evt->eventType) { - case kSurface_ANPEventType: - switch (evt->data.surface.action) { - case kCreated_ANPSurfaceAction: - m_surfaceReady = true; - drawCleanPlugin(); - return 1; - case kDestroyed_ANPSurfaceAction: - m_surfaceReady = false; - return 1; - case kChanged_ANPSurfaceAction: - // get the plugin's dimensions according to the DOM - PluginObject *obj = (PluginObject*) inst()->pdata; - const int pW = obj->window->width; - const int pH = obj->window->height; - // get the plugin's surface dimensions - const int sW = evt->data.surface.data.changed.width; - const int sH = evt->data.surface.data.changed.height; - if (pW != sW || pH != sH) - gLogI.log(inst(), kError_ANPLogType, - "----%p Invalid Surface Dimensions (%d,%d):(%d,%d)", - inst(), pW, pH, sW, sH); - return 1; - } - break; - case kTouch_ANPEventType: { float x = (float) evt->data.touch.x; float y = (float) evt->data.touch.y; diff --git a/samples/BrowserPlugin/jni/paint/PaintPlugin.h b/samples/BrowserPlugin/jni/paint/PaintPlugin.h index 7e6f23540..8ff561c49 100644 --- a/samples/BrowserPlugin/jni/paint/PaintPlugin.h +++ b/samples/BrowserPlugin/jni/paint/PaintPlugin.h @@ -29,12 +29,17 @@ #ifndef paintPlugin__DEFINED #define paintPlugin__DEFINED -class PaintPlugin : public SubPlugin { +class PaintPlugin : public SurfaceSubPlugin { public: PaintPlugin(NPP inst); virtual ~PaintPlugin(); virtual bool supportsDrawingModel(ANPDrawingModel); virtual int16 handleEvent(const ANPEvent* evt); + virtual void surfaceCreated(JNIEnv* env, jobject surface); + virtual void surfaceChanged(int format, int width, int height); + virtual void surfaceDestroyed(); + virtual bool isFixedSurface(); + private: void drawCleanPlugin(ANPCanvas* canvas = NULL); ANPCanvas* getCanvas(ANPRectI* dirtyRect = NULL); @@ -49,9 +54,9 @@ private: bool m_isTouchActive; bool m_isTouchCurrentInput; - bool m_surfaceReady; - ANPSurface* m_surface; + JavaVM* m_vm; + jobject m_surface; ANPPath* m_touchPath; ANPRectF m_drawingSurface; diff --git a/samples/BrowserPlugin/src/com/android/sampleplugin/SamplePluginStub.java b/samples/BrowserPlugin/src/com/android/sampleplugin/SamplePluginStub.java index 0b474a464..3c0a0c70c 100644 --- a/samples/BrowserPlugin/src/com/android/sampleplugin/SamplePluginStub.java +++ b/samples/BrowserPlugin/src/com/android/sampleplugin/SamplePluginStub.java @@ -19,8 +19,11 @@ package com.android.sampleplugin; import android.content.Context; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; +import android.view.SurfaceHolder; +import android.view.SurfaceView; import android.view.View; import android.view.WindowManager; +import android.view.SurfaceHolder.Callback; import android.view.ViewGroup.LayoutParams; import android.webkit.PluginStub; import android.widget.FrameLayout; @@ -28,29 +31,53 @@ import android.widget.MediaController; import android.widget.VideoView; import com.android.sampleplugin.graphics.CubeRenderer; -public class SamplePluginStub extends PluginStub { +public class SamplePluginStub implements PluginStub { - private int npp; - - public SamplePluginStub(int npp) { - super(npp); - this.npp = npp; - } - - public View getEmbeddedView(Context context) { - // TODO Auto-generated method stub - return null; + static { + //needed for jni calls + System.loadLibrary("sampleplugin"); } - public View getFullScreenView(Context context) { + public View getEmbeddedView(final int npp, Context context) { + + final SurfaceView view = new SurfaceView(context); + + /* You can do all sorts of interesting operations on the surface view + * here. We illustrate a few of the important operations below. + */ + + //TODO get pixel format from the subplugin (via jni) + view.getHolder().setFormat(PixelFormat.RGBA_8888); + view.getHolder().addCallback(new Callback() { + + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + nativeSurfaceChanged(npp, format, width, height); + } + + public void surfaceCreated(SurfaceHolder holder) { + nativeSurfaceCreated(npp, view); + } + + public void surfaceDestroyed(SurfaceHolder holder) { + nativeSurfaceDestroyed(npp); + } + + }); + + if (nativeIsFixedSurface(npp)) { + //TODO get the fixed dimensions from the plugin + //view.getHolder().setFixedSize(width, height); + } + + return view; + } + + public View getFullScreenView(int npp, Context context) { /* TODO make this aware of the plugin instance and get the video file * from the plugin. */ - //needed for jni calls - System.loadLibrary("sampleplugin"); - FrameLayout layout = new FrameLayout(context); LayoutParams fp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); layout.setLayoutParams(fp); @@ -84,6 +111,8 @@ public class SamplePluginStub extends PluginStub { return layout; } - public native String nativeStringFromJNI(); - + private native void nativeSurfaceCreated(int npp, View surfaceView); + private native void nativeSurfaceChanged(int npp, int format, int width, int height); + private native void nativeSurfaceDestroyed(int npp); + private native boolean nativeIsFixedSurface(int npp); }