Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54a181b1 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Make real API for native code to get its window.

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

Change-Id: I890d71b6e15d4af71e6cf81b327961d7061ec1c2
parent 65c83b90
Loading
Loading
Loading
Loading
+18 −7
Original line number Diff line number Diff line
@@ -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);
    }
}
+56 −22
Original line number Diff line number Diff line
@@ -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 },
};
@@ -426,6 +453,13 @@ int register_android_app_NativeActivity(JNIEnv* env)
            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));
+2 −1
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
/*
 * 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
+5 −6
Original line number Diff line number Diff line
@@ -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;
}
Loading