Merge "First pass at NativeActivity." into kraken

This commit is contained in:
Dianne Hackborn
2010-05-05 15:18:59 -07:00
committed by Android (Google) Code Review
6 changed files with 425 additions and 0 deletions

View File

@ -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="&quot;android.app.lib_name&quot;"
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"

View 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);
}
}

View File

@ -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 \

View File

@ -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),
};
/*

View 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));
}
}

View 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