Merge "First pass at NativeActivity." into kraken
This commit is contained in:
committed by
Android (Google) Code Review
commit
f41f444d12
@ -26276,6 +26276,34 @@
|
||||
</parameter>
|
||||
</method>
|
||||
</class>
|
||||
<class name="NativeActivity"
|
||||
extends="android.app.Activity"
|
||||
abstract="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<constructor name="NativeActivity"
|
||||
type="android.app.NativeActivity"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</constructor>
|
||||
<field name="META_DATA_LIB_NAME"
|
||||
type="java.lang.String"
|
||||
transient="false"
|
||||
volatile="false"
|
||||
value=""android.app.lib_name""
|
||||
static="true"
|
||||
final="true"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
</field>
|
||||
</class>
|
||||
<class name="Notification"
|
||||
extends="java.lang.Object"
|
||||
abstract="false"
|
||||
@ -220539,6 +220567,19 @@
|
||||
<parameter name="parent" type="java.lang.ClassLoader">
|
||||
</parameter>
|
||||
</constructor>
|
||||
<method name="findLibrary"
|
||||
return="java.lang.String"
|
||||
abstract="false"
|
||||
native="false"
|
||||
synchronized="false"
|
||||
static="false"
|
||||
final="false"
|
||||
deprecated="not deprecated"
|
||||
visibility="public"
|
||||
>
|
||||
<parameter name="libname" type="java.lang.String">
|
||||
</parameter>
|
||||
</method>
|
||||
</class>
|
||||
<class name="PotentialDeadlockError"
|
||||
extends="java.lang.VirtualMachineError"
|
||||
|
122
core/java/android/app/NativeActivity.java
Normal file
122
core/java/android/app/NativeActivity.java
Normal file
@ -0,0 +1,122 @@
|
||||
package android.app;
|
||||
|
||||
import dalvik.system.PathClassLoader;
|
||||
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Convenience for implementing an activity that will be implemented
|
||||
* purely in native code. That is, a game (or game-like thing).
|
||||
*/
|
||||
public class NativeActivity extends Activity {
|
||||
public static final String META_DATA_LIB_NAME = "android.app.lib_name";
|
||||
|
||||
private int mNativeHandle;
|
||||
|
||||
private native int loadNativeCode(String path);
|
||||
private native void unloadNativeCode(int handle);
|
||||
|
||||
private native void onStartNative(int handle);
|
||||
private native void onResumeNative(int handle);
|
||||
private native void onSaveInstanceStateNative(int handle);
|
||||
private native void onPauseNative(int handle);
|
||||
private native void onStopNative(int handle);
|
||||
private native void onLowMemoryNative(int handle);
|
||||
private native void onWindowFocusChangedNative(int handle, boolean focused);
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
String libname = "main";
|
||||
ActivityInfo ai;
|
||||
|
||||
try {
|
||||
ai = getPackageManager().getActivityInfo(
|
||||
getIntent().getComponent(), PackageManager.GET_META_DATA);
|
||||
if (ai.metaData != null) {
|
||||
String ln = ai.metaData.getString(META_DATA_LIB_NAME);
|
||||
if (ln != null) libname = ln;
|
||||
}
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
throw new RuntimeException("Error getting activity info", e);
|
||||
}
|
||||
|
||||
String path = null;
|
||||
|
||||
if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) == 0) {
|
||||
// If the application does not have (Java) code, then no ClassLoader
|
||||
// has been set up for it. We will need to do our own search for
|
||||
// the native code.
|
||||
path = ai.applicationInfo.dataDir + "/lib/" + System.mapLibraryName(libname);
|
||||
if (!(new File(path)).exists()) {
|
||||
path = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (path == null) {
|
||||
path = ((PathClassLoader)getClassLoader()).findLibrary(libname);
|
||||
}
|
||||
|
||||
if (path == null) {
|
||||
throw new IllegalArgumentException("Unable to find native library: " + libname);
|
||||
}
|
||||
|
||||
mNativeHandle = loadNativeCode(path);
|
||||
if (mNativeHandle == 0) {
|
||||
throw new IllegalArgumentException("Unable to load native library: " + path);
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
unloadNativeCode(mNativeHandle);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
onLowMemoryNative(mNativeHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
onPauseNative(mNativeHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
onResumeNative(mNativeHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
onSaveInstanceStateNative(mNativeHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
onStartNative(mNativeHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
onStopNative(mNativeHandle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
onWindowFocusChangedNative(mNativeHandle, hasFocus);
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ LOCAL_SRC_FILES:= \
|
||||
Time.cpp \
|
||||
com_google_android_gles_jni_EGLImpl.cpp \
|
||||
com_google_android_gles_jni_GLImpl.cpp.arm \
|
||||
android_app_NativeActivity.cpp \
|
||||
android_opengl_GLES10.cpp \
|
||||
android_opengl_GLES10Ext.cpp \
|
||||
android_opengl_GLES11.cpp \
|
||||
|
@ -159,6 +159,7 @@ extern int register_android_backup_BackupDataInput(JNIEnv *env);
|
||||
extern int register_android_backup_BackupDataOutput(JNIEnv *env);
|
||||
extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
|
||||
extern int register_android_backup_BackupHelperDispatcher(JNIEnv *env);
|
||||
extern int register_android_app_NativeActivity(JNIEnv *env);
|
||||
|
||||
static AndroidRuntime* gCurRuntime = NULL;
|
||||
|
||||
@ -1281,6 +1282,8 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_backup_BackupDataOutput),
|
||||
REG_JNI(register_android_backup_FileBackupHelperBase),
|
||||
REG_JNI(register_android_backup_BackupHelperDispatcher),
|
||||
|
||||
REG_JNI(register_android_app_NativeActivity),
|
||||
};
|
||||
|
||||
/*
|
||||
|
190
core/jni/android_app_NativeActivity.cpp
Normal file
190
core/jni/android_app_NativeActivity.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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 "NativeActivity"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "JNIHelp.h"
|
||||
#include <android_runtime/AndroidRuntime.h>
|
||||
#include <android/native_activity.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
namespace android
|
||||
{
|
||||
|
||||
struct NativeCode {
|
||||
android_activity_t activity;
|
||||
android_activity_callbacks_t callbacks;
|
||||
|
||||
void* dlhandle;
|
||||
|
||||
android_activity_create_t* createActivityFunc;
|
||||
void* clientContext;
|
||||
};
|
||||
|
||||
static jint
|
||||
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path)
|
||||
{
|
||||
const char* pathStr = env->GetStringUTFChars(path, NULL);
|
||||
NativeCode* code = NULL;
|
||||
|
||||
void* handle = dlopen(pathStr, RTLD_LAZY);
|
||||
|
||||
env->ReleaseStringUTFChars(path, pathStr);
|
||||
|
||||
if (handle != NULL) {
|
||||
code = new NativeCode();
|
||||
code->dlhandle = handle;
|
||||
code->createActivityFunc = (android_activity_create_t*)
|
||||
dlsym(handle, "android_onCreateActivity");
|
||||
if (code->createActivityFunc == NULL) {
|
||||
LOGW("android_onCreateActivity not found");
|
||||
delete code;
|
||||
dlclose(handle);
|
||||
return 0;
|
||||
}
|
||||
memset(&code->activity, sizeof(code->activity), 0);
|
||||
memset(&code->callbacks, sizeof(code->callbacks), 0);
|
||||
code->activity.callbacks = &code->callbacks;
|
||||
code->activity.env = env;
|
||||
code->activity.clazz = clazz;
|
||||
code->createActivityFunc(&code->activity, NULL, 0);
|
||||
}
|
||||
|
||||
return (jint)code;
|
||||
}
|
||||
|
||||
static void
|
||||
unloadNativeCode_native(JNIEnv* env, jobject clazz, jint handle)
|
||||
{
|
||||
if (handle != 0) {
|
||||
NativeCode* code = (NativeCode*)handle;
|
||||
if (code->callbacks.onDestroy != NULL) {
|
||||
code->callbacks.onDestroy(&code->activity);
|
||||
}
|
||||
dlclose(code->dlhandle);
|
||||
delete code;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onStart_native(JNIEnv* env, jobject clazz, jint handle)
|
||||
{
|
||||
if (handle != 0) {
|
||||
NativeCode* code = (NativeCode*)handle;
|
||||
if (code->callbacks.onStart != NULL) {
|
||||
code->callbacks.onStart(&code->activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onResume_native(JNIEnv* env, jobject clazz, jint handle)
|
||||
{
|
||||
if (handle != 0) {
|
||||
NativeCode* code = (NativeCode*)handle;
|
||||
if (code->callbacks.onResume != NULL) {
|
||||
code->callbacks.onResume(&code->activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onSaveInstanceState_native(JNIEnv* env, jobject clazz, jint handle)
|
||||
{
|
||||
if (handle != 0) {
|
||||
NativeCode* code = (NativeCode*)handle;
|
||||
if (code->callbacks.onSaveInstanceState != NULL) {
|
||||
size_t len = 0;
|
||||
code->callbacks.onSaveInstanceState(&code->activity, &len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onPause_native(JNIEnv* env, jobject clazz, jint handle)
|
||||
{
|
||||
if (handle != 0) {
|
||||
NativeCode* code = (NativeCode*)handle;
|
||||
if (code->callbacks.onPause != NULL) {
|
||||
code->callbacks.onPause(&code->activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onStop_native(JNIEnv* env, jobject clazz, jint handle)
|
||||
{
|
||||
if (handle != 0) {
|
||||
NativeCode* code = (NativeCode*)handle;
|
||||
if (code->callbacks.onStop != NULL) {
|
||||
code->callbacks.onStop(&code->activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onLowMemory_native(JNIEnv* env, jobject clazz, jint handle)
|
||||
{
|
||||
if (handle != 0) {
|
||||
NativeCode* code = (NativeCode*)handle;
|
||||
if (code->callbacks.onLowMemory != NULL) {
|
||||
code->callbacks.onLowMemory(&code->activity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
onWindowFocusChanged_native(JNIEnv* env, jobject clazz, jint handle, jboolean focused)
|
||||
{
|
||||
if (handle != 0) {
|
||||
NativeCode* code = (NativeCode*)handle;
|
||||
if (code->callbacks.onWindowFocusChanged != NULL) {
|
||||
code->callbacks.onWindowFocusChanged(&code->activity, focused ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const JNINativeMethod g_methods[] = {
|
||||
{ "loadNativeCode", "(Ljava/lang/String;)I", (void*)loadNativeCode_native },
|
||||
{ "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
|
||||
{ "onStartNative", "(I)V", (void*)onStart_native },
|
||||
{ "onResumeNative", "(I)V", (void*)onResume_native },
|
||||
{ "onSaveInstanceStateNative", "(I)V", (void*)onSaveInstanceState_native },
|
||||
{ "onPauseNative", "(I)V", (void*)onPause_native },
|
||||
{ "onStopNative", "(I)V", (void*)onStop_native },
|
||||
{ "onLowMemoryNative", "(I)V", (void*)onLowMemory_native },
|
||||
{ "onWindowFocusChangedNative", "(IZ)V", (void*)onWindowFocusChanged_native },
|
||||
};
|
||||
|
||||
static const char* const kNativeActivityPathName = "android/app/NativeActivity";
|
||||
|
||||
int register_android_app_NativeActivity(JNIEnv* env)
|
||||
{
|
||||
//LOGD("register_android_app_NativeActivity");
|
||||
|
||||
jclass clazz;
|
||||
|
||||
clazz = env->FindClass(kNativeActivityPathName);
|
||||
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.app.NativeActivity");
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(
|
||||
env, kNativeActivityPathName,
|
||||
g_methods, NELEM(g_methods));
|
||||
}
|
||||
|
||||
}
|
68
native/include/android/native_activity.h
Normal file
68
native/include/android/native_activity.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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_NATIVE_ACTIVITY_H
|
||||
#define ANDROID_NATIVE_ACTIVITY_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct android_activity_callbacks_t;
|
||||
|
||||
typedef struct android_activity_t {
|
||||
struct android_activity_callbacks_t* callbacks;
|
||||
|
||||
JNIEnv* env;
|
||||
jobject clazz;
|
||||
|
||||
void* instance;
|
||||
} android_activity_t;
|
||||
|
||||
typedef struct android_activity_callbacks_t {
|
||||
void (*onStart)(android_activity_t* activity);
|
||||
void (*onResume)(android_activity_t* activity);
|
||||
void* (*onSaveInstanceState)(android_activity_t* activity, size_t* outSize);
|
||||
void (*onPause)(android_activity_t* activity);
|
||||
void (*onStop)(android_activity_t* activity);
|
||||
void (*onDestroy)(android_activity_t* activity);
|
||||
|
||||
void (*onLowMemory)(android_activity_t* activity);
|
||||
void (*onWindowFocusChanged)(android_activity_t* activity, int hasFocus);
|
||||
} android_activity_callbacks_t;
|
||||
|
||||
typedef void android_activity_create_t(android_activity_t* activity,
|
||||
void* savedState, size_t savedStateSize);
|
||||
|
||||
extern android_activity_create_t android_onCreateActivity;
|
||||
|
||||
#if 0
|
||||
extern android_onCreateActivity(android_activity_t activity,
|
||||
void* savedState, size_t savedStateSize);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // ANDROID_NATIVE_ACTIVITY_H
|
||||
|
Reference in New Issue
Block a user