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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
31
core/jni/android_view_Surface.h
Normal file
31
core/jni/android_view_Surface.h
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ include $(CLEAR_VARS)
|
||||
#
|
||||
LOCAL_SRC_FILES:= \
|
||||
activity.cpp \
|
||||
input.cpp
|
||||
input.cpp \
|
||||
native_window.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libandroid_runtime \
|
||||
|
||||
41
native/android/native_window.cpp
Normal file
41
native/android/native_window.cpp
Normal 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);
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user