Make real API for native code to get its window.

Added implementation to use ANativeWindow and provide
it to a NativeActivity.

Change-Id: I890d71b6e15d4af71e6cf81b327961d7061ec1c2
This commit is contained in:
Dianne Hackborn
2010-06-30 18:35:14 -07:00
parent 65c83b906d
commit 54a181b1a2
9 changed files with 185 additions and 55 deletions

View File

@@ -5,12 +5,14 @@ import dalvik.system.PathClassLoader;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Looper;
import android.os.MessageQueue;
import android.view.InputChannel;
import android.view.InputQueue;
import android.view.KeyEvent;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.View;
@@ -41,10 +43,10 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
private native void onStopNative(int handle);
private native void onLowMemoryNative(int handle);
private native void onWindowFocusChangedNative(int handle, boolean focused);
private native void onSurfaceCreatedNative(int handle, SurfaceHolder holder);
private native void onSurfaceChangedNative(int handle, SurfaceHolder holder,
private native void onSurfaceCreatedNative(int handle, Surface surface);
private native void onSurfaceChangedNative(int handle, Surface surface,
int format, int width, int height);
private native void onSurfaceDestroyedNative(int handle, SurfaceHolder holder);
private native void onSurfaceDestroyedNative(int handle);
private native void onInputChannelCreatedNative(int handle, InputChannel channel);
private native void onInputChannelDestroyedNative(int handle, InputChannel channel);
@@ -55,6 +57,7 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
getWindow().takeSurface(this);
getWindow().takeInputQueue(this);
getWindow().setFormat(PixelFormat.RGB_565);
try {
ai = getPackageManager().getActivityInfo(
@@ -98,7 +101,7 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
protected void onDestroy() {
mDestroyed = true;
if (mCurSurfaceHolder != null) {
onSurfaceDestroyedNative(mNativeHandle, mCurSurfaceHolder);
onSurfaceDestroyedNative(mNativeHandle);
mCurSurfaceHolder = null;
}
if (mCurInputQueue != null) {
@@ -158,21 +161,21 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
public void surfaceCreated(SurfaceHolder holder) {
if (!mDestroyed) {
mCurSurfaceHolder = holder;
onSurfaceCreatedNative(mNativeHandle, holder);
onSurfaceCreatedNative(mNativeHandle, holder.getSurface());
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if (!mDestroyed) {
mCurSurfaceHolder = holder;
onSurfaceChangedNative(mNativeHandle, holder, format, width, height);
onSurfaceChangedNative(mNativeHandle, holder.getSurface(), format, width, height);
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
mCurSurfaceHolder = null;
if (!mDestroyed) {
onSurfaceDestroyedNative(mNativeHandle, holder);
onSurfaceDestroyedNative(mNativeHandle);
}
}
@@ -196,4 +199,12 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback,
decor.dispatchKeyEvent(event);
}
}
void setWindowFlags(int flags, int mask) {
getWindow().setFlags(flags, mask);
}
void setWindowFormat(int format) {
getWindow().setFormat(format);
}
}

View File

@@ -22,6 +22,8 @@
#include <android_runtime/AndroidRuntime.h>
#include <android/native_activity.h>
#include <surfaceflinger/Surface.h>
#include <ui/egl/android_natives.h>
#include <ui/InputTransport.h>
#include <utils/PollLoop.h>
@@ -29,6 +31,7 @@
#include "android_os_MessageQueue.h"
#include "android_view_InputChannel.h"
#include "android_view_KeyEvent.h"
#include "android_view_Surface.h"
namespace android
{
@@ -37,8 +40,16 @@ static struct {
jclass clazz;
jmethodID dispatchUnhandledKeyEvent;
jmethodID setWindowFlags;
jmethodID setWindowFormat;
} gNativeActivityClassInfo;
// ------------------------------------------------------------------------
/*
* Specialized input queue that allows unhandled key events to be dispatched
* back to the native activity's Java framework code.
*/
struct MyInputQueue : AInputQueue {
explicit MyInputQueue(const android::sp<android::InputChannel>& channel, int workWrite)
: AInputQueue(channel), mWorkWrite(workWrite) {
@@ -74,13 +85,18 @@ struct MyInputQueue : AInputQueue {
Vector<KeyEvent*> mPendingKeys;
};
// ------------------------------------------------------------------------
/*
* Native state for interacting with the NativeActivity class.
*/
struct NativeCode {
NativeCode(void* _dlhandle, ANativeActivity_createFunc* _createFunc) {
memset(&activity, sizeof(activity), 0);
memset(&callbacks, sizeof(callbacks), 0);
dlhandle = _dlhandle;
createActivityFunc = _createFunc;
surface = NULL;
nativeWindow = NULL;
inputChannel = NULL;
nativeInputQueue = NULL;
mainWorkRead = mainWorkWrite = -1;
@@ -104,18 +120,18 @@ struct NativeCode {
if (mainWorkRead >= 0) close(mainWorkRead);
if (mainWorkWrite >= 0) close(mainWorkWrite);
if (dlhandle != NULL) {
dlclose(dlhandle);
// for now don't unload... we probably should clean this
// up and only keep one open dlhandle per proc, since there
// is really no benefit to unloading the code.
//dlclose(dlhandle);
}
}
void setSurface(jobject _surface) {
if (surface != NULL) {
activity.env->DeleteGlobalRef(surface);
}
if (_surface != NULL) {
surface = activity.env->NewGlobalRef(_surface);
nativeWindow = android_Surface_getNativeWindow(activity.env, _surface);
} else {
surface = NULL;
nativeWindow = NULL;
}
}
@@ -150,7 +166,7 @@ struct NativeCode {
void* dlhandle;
ANativeActivity_createFunc* createActivityFunc;
jobject surface;
sp<ANativeWindow> nativeWindow;
jobject inputChannel;
struct MyInputQueue* nativeInputQueue;
@@ -160,6 +176,11 @@ struct NativeCode {
sp<PollLoop> pollLoop;
};
// ------------------------------------------------------------------------
/*
* Callback for handling native events on the application's main thread.
*/
static bool mainWorkCallback(int fd, int events, void* data) {
NativeCode* code = (NativeCode*)data;
if ((events & POLLIN) != 0) {
@@ -180,6 +201,8 @@ static bool mainWorkCallback(int fd, int events, void* data) {
return true;
}
// ------------------------------------------------------------------------
static jint
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jobject messageQueue)
{
@@ -323,9 +346,9 @@ onSurfaceCreated_native(JNIEnv* env, jobject clazz, jint handle, jobject surface
if (handle != 0) {
NativeCode* code = (NativeCode*)handle;
code->setSurface(surface);
if (code->callbacks.onSurfaceCreated != NULL) {
code->callbacks.onSurfaceCreated(&code->activity,
(ASurfaceHolder*)code->surface);
if (code->nativeWindow != NULL && code->callbacks.onNativeWindowCreated != NULL) {
code->callbacks.onNativeWindowCreated(&code->activity,
code->nativeWindow.get());
}
}
}
@@ -336,9 +359,13 @@ onSurfaceChanged_native(JNIEnv* env, jobject clazz, jint handle, jobject surface
{
if (handle != 0) {
NativeCode* code = (NativeCode*)handle;
if (code->surface != NULL && code->callbacks.onSurfaceChanged != NULL) {
code->callbacks.onSurfaceChanged(&code->activity,
(ASurfaceHolder*)code->surface, format, width, height);
sp<ANativeWindow> oldNativeWindow = code->nativeWindow;
code->setSurface(surface);
if (oldNativeWindow != code->nativeWindow) {
if (code->nativeWindow != NULL && code->callbacks.onNativeWindowChanged != NULL) {
code->callbacks.onNativeWindowChanged(&code->activity,
code->nativeWindow.get());
}
}
}
}
@@ -348,9 +375,9 @@ onSurfaceDestroyed_native(JNIEnv* env, jobject clazz, jint handle, jobject surfa
{
if (handle != 0) {
NativeCode* code = (NativeCode*)handle;
if (code->surface != NULL && code->callbacks.onSurfaceDestroyed != NULL) {
code->callbacks.onSurfaceDestroyed(&code->activity,
(ASurfaceHolder*)code->surface);
if (code->nativeWindow != NULL && code->callbacks.onNativeWindowDestroyed != NULL) {
code->callbacks.onNativeWindowDestroyed(&code->activity,
code->nativeWindow.get());
}
code->setSurface(NULL);
}
@@ -398,9 +425,9 @@ static const JNINativeMethod g_methods[] = {
{ "onStopNative", "(I)V", (void*)onStop_native },
{ "onLowMemoryNative", "(I)V", (void*)onLowMemory_native },
{ "onWindowFocusChangedNative", "(IZ)V", (void*)onWindowFocusChanged_native },
{ "onSurfaceCreatedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceCreated_native },
{ "onSurfaceChangedNative", "(ILandroid/view/SurfaceHolder;III)V", (void*)onSurfaceChanged_native },
{ "onSurfaceDestroyedNative", "(ILandroid/view/SurfaceHolder;)V", (void*)onSurfaceDestroyed_native },
{ "onSurfaceCreatedNative", "(ILandroid/view/Surface;)V", (void*)onSurfaceCreated_native },
{ "onSurfaceChangedNative", "(ILandroid/view/Surface;III)V", (void*)onSurfaceChanged_native },
{ "onSurfaceDestroyedNative", "(I)V", (void*)onSurfaceDestroyed_native },
{ "onInputChannelCreatedNative", "(ILandroid/view/InputChannel;)V", (void*)onInputChannelCreated_native },
{ "onInputChannelDestroyedNative", "(ILandroid/view/InputChannel;)V", (void*)onInputChannelDestroyed_native },
};
@@ -421,11 +448,18 @@ int register_android_app_NativeActivity(JNIEnv* env)
//LOGD("register_android_app_NativeActivity");
FIND_CLASS(gNativeActivityClassInfo.clazz, kNativeActivityPathName);
GET_METHOD_ID(gNativeActivityClassInfo.dispatchUnhandledKeyEvent,
gNativeActivityClassInfo.clazz,
"dispatchUnhandledKeyEvent", "(Landroid/view/KeyEvent;)V");
GET_METHOD_ID(gNativeActivityClassInfo.setWindowFlags,
gNativeActivityClassInfo.clazz,
"setWindowFlags", "(II)V");
GET_METHOD_ID(gNativeActivityClassInfo.setWindowFormat,
gNativeActivityClassInfo.clazz,
"setWindowFormat", "(I)V");
return AndroidRuntime::registerNativeMethods(
env, kNativeActivityPathName,
g_methods, NELEM(g_methods));

View File

@@ -33,6 +33,7 @@
#include "jni.h"
#include <android_runtime/AndroidRuntime.h>
#include "android_view_Surface.h"
#include <utils/misc.h>
@@ -179,7 +180,7 @@ static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
return result;
}
EGLNativeWindowType android_Surface_getEGLNativeWindow(
sp<ANativeWindow> android_Surface_getNativeWindow(
JNIEnv* env, jobject clazz) {
return getSurface(env, clazz).get();
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2010 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.
*/
#ifndef _ANDROID_VIEW_SURFACE_H
#define _ANDROID_VIEW_SURFACE_H
#include <android/native_window.h>
#include "jni.h"
namespace android {
extern sp<ANativeWindow> android_Surface_getNativeWindow(
JNIEnv* env, jobject clazz);
} // namespace android
#endif // _ANDROID_VIEW_SURFACE_H

View File

@@ -25,10 +25,9 @@
#include <SkBitmap.h>
#include <SkPixelRef.h>
namespace android {
#include "android_view_Surface.h"
extern EGLNativeWindowType android_Surface_getEGLNativeWindow(
JNIEnv* env, jobject clazz);
namespace android {
static jclass gDisplay_class;
static jclass gContext_class;
@@ -325,7 +324,7 @@ static jint jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject disp
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext cnf = getConfig(_env, config);
EGLNativeWindowType window = 0;
sp<ANativeWindow> window;
if (native_window == NULL) {
not_valid_surface:
doThrow(_env, "java/lang/IllegalArgumentException",
@@ -333,12 +332,12 @@ not_valid_surface:
return 0;
}
window = android_Surface_getEGLNativeWindow(_env, native_window);
window = android_Surface_getNativeWindow(_env, native_window);
if (window == NULL)
goto not_valid_surface;
jint* base = beginNativeAttribList(_env, attrib_list);
EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window, base);
EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
endNativeAttributeList(_env, attrib_list, base);
return (jint)sur;
}

View File

@@ -7,7 +7,8 @@ include $(CLEAR_VARS)
#
LOCAL_SRC_FILES:= \
activity.cpp \
input.cpp
input.cpp \
native_window.cpp
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2010 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.
*/
#define LOG_TAG "Surface"
#include <utils/Log.h>
#include <android/native_window.h>
#include <surfaceflinger/Surface.h>
using android::Surface;
static int32_t getWindowProp(ANativeWindow* window, int what) {
int value;
int res = window->query(window, what, &value);
return res < 0 ? res : value;
}
int32_t ANativeWindow_getWidth(ANativeWindow* window) {
return getWindowProp(window, NATIVE_WINDOW_WIDTH);
}
int32_t ANativeWindow_getHeight(ANativeWindow* window) {
return getWindowProp(window, NATIVE_WINDOW_HEIGHT);
}
int32_t ANativeWindow_getFormat(ANativeWindow* window) {
return getWindowProp(window, NATIVE_WINDOW_FORMAT);
}

View File

@@ -24,15 +24,12 @@
#include <jni.h>
#include <android/input.h>
#include <android/native_window.h>
#ifdef __cplusplus
extern "C" {
#endif
// Temporary until native surface API is defined.
struct ASurfaceHolder;
typedef struct ASurfaceHolder ASurfaceHolder;
struct ANativeActivityCallbacks;
/**
@@ -129,30 +126,28 @@ typedef struct ANativeActivityCallbacks {
void (*onWindowFocusChanged)(ANativeActivity* activity, int hasFocus);
/**
* The drawing surface for this native activity has been created. You
* can use the given surface object to start drawing. NOTE: surface
* drawing API is not yet defined.
* The drawing window for this native activity has been created. You
* can use the given native window object to start drawing.
*/
void (*onSurfaceCreated)(ANativeActivity* activity, ASurfaceHolder* surface);
void (*onNativeWindowCreated)(ANativeActivity* activity, ANativeWindow* window);
/**
* The drawing surface for this native activity has changed. The surface
* given here is guaranteed to be the same as the one last given to
* onSurfaceCreated. This is simply to inform you about interesting
* changed to that surface.
* The drawing window for this native activity has changed. During this time,
* old ANativeWindow object is still valid but no longer active and drawing
* should switch to the new ANativeWindow given here. After returning from
* this function, you must not touch the old window.
*/
void (*onSurfaceChanged)(ANativeActivity* activity, ASurfaceHolder* surface,
int format, int width, int height);
void (*onNativeWindowChanged)(ANativeActivity* activity, ANativeWindow* window);
/**
* The drawing surface for this native activity is going to be destroyed.
* You MUST ensure that you do not touch the surface object after returning
* from this function: in the common case of drawing to the surface from
* The drawing window for this native activity is going to be destroyed.
* You MUST ensure that you do not touch the window object after returning
* from this function: in the common case of drawing to the window from
* another thread, that means the implementation of this callback must
* properly synchronize with the other thread to stop its drawing before
* returning from here.
*/
void (*onSurfaceDestroyed)(ANativeActivity* activity, ASurfaceHolder* surface);
void (*onNativeWindowDestroyed)(ANativeActivity* activity, ANativeWindow* window);
/**
* The input queue for this native activity's window has been created.

View File

@@ -25,6 +25,23 @@ extern "C" {
struct ANativeWindow;
typedef struct ANativeWindow ANativeWindow;
/*
* Return the current width in pixels of the window surface. Returns a
* negative value on error.
*/
int32_t ANativeWindow_getWidth(ANativeWindow* window);
/*
* Return the current height in pixels of the window surface. Returns a
* negative value on error.
*/
int32_t ANativeWindow_getHeight(ANativeWindow* window);
/*
* Return the current pixel format of the window surface. Returns a
* negative value on error.
*/
int32_t ANativeWindow_getFormat(ANativeWindow* window);
#ifdef __cplusplus
};