27f8002e59
This change adds four new public classes that expose a static OpenGL ES 1.1 API: android.opengl.GLES10 android.opengl.GLES10Ext android.opengl.GLES11 android.opengl.GLES11Ext Benefits: + The static API is slightly faster (1% to 4%) than the existing Interface based JSR239 API. + The static API is similar to the C API, which should make it easier to import C-based example code. + The static API provides a clear path for adding new OpenGL ES 1.1 extensions and OpenGL ES 2.0 APIs, neither of which currently have a JSR standard. Example: import static android.opengl.GLES10.*; ... glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); Note that it is possible to mix-and-match calls to both the static and JSR239 APIs. This works because neither API maintains state. They both call through to the same underlying C OpenGL ES APIs. Implementation details: This change enhances the "glgen" "gen" script to generate both the original JSR239 and new static OpenGL ES APIs. The contents of the generated JSR239 classes remained the same as before, so there is no need to check in new versions of the generated JSR239 classes. As part of this work the gen script was updated to be somewhat more robust, and to work with git instead of perforce. The script prints out commands to git add the generated files, but leaves it up to the script runner to actually execute those commands.
1178 lines
38 KiB
C++
1178 lines
38 KiB
C++
/* //device/libs/android_runtime/AndroidRuntime.cpp
|
|
**
|
|
** Copyright 2006, 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 "AndroidRuntime"
|
|
//#define LOG_NDEBUG 0
|
|
|
|
#include <android_runtime/AndroidRuntime.h>
|
|
#include <utils/IBinder.h>
|
|
#include <utils/IServiceManager.h>
|
|
#include <utils/Log.h>
|
|
#include <utils/misc.h>
|
|
#include <utils/Parcel.h>
|
|
#include <utils/string_array.h>
|
|
#include <utils/threads.h>
|
|
#include <cutils/properties.h>
|
|
|
|
#include <SkGraphics.h>
|
|
#include <SkImageDecoder.h>
|
|
|
|
#include "jni.h"
|
|
#include "JNIHelp.h"
|
|
#include "android_util_Binder.h"
|
|
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <signal.h>
|
|
#include <dirent.h>
|
|
#include <assert.h>
|
|
|
|
|
|
using namespace android;
|
|
|
|
extern void register_BindTest();
|
|
|
|
extern int register_android_os_Binder(JNIEnv* env);
|
|
extern int register_android_os_Process(JNIEnv* env);
|
|
extern int register_android_graphics_Bitmap(JNIEnv*);
|
|
extern int register_android_graphics_BitmapFactory(JNIEnv*);
|
|
extern int register_android_graphics_Camera(JNIEnv* env);
|
|
extern int register_android_graphics_Graphics(JNIEnv* env);
|
|
extern int register_android_graphics_Interpolator(JNIEnv* env);
|
|
extern int register_android_graphics_LayerRasterizer(JNIEnv*);
|
|
extern int register_android_graphics_MaskFilter(JNIEnv* env);
|
|
extern int register_android_graphics_Movie(JNIEnv* env);
|
|
extern int register_android_graphics_NinePatch(JNIEnv*);
|
|
extern int register_android_graphics_PathEffect(JNIEnv* env);
|
|
extern int register_android_graphics_Region(JNIEnv* env);
|
|
extern int register_android_graphics_Shader(JNIEnv* env);
|
|
extern int register_android_graphics_Typeface(JNIEnv* env);
|
|
|
|
extern int register_com_google_android_gles_jni_EGLImpl(JNIEnv* env);
|
|
extern int register_com_google_android_gles_jni_GLImpl(JNIEnv* env);
|
|
extern int register_android_opengl_jni_GLES10(JNIEnv* env);
|
|
extern int register_android_opengl_jni_GLES10Ext(JNIEnv* env);
|
|
extern int register_android_opengl_jni_GLES11(JNIEnv* env);
|
|
extern int register_android_opengl_jni_GLES11Ext(JNIEnv* env);
|
|
|
|
extern int register_android_hardware_Camera(JNIEnv *env);
|
|
|
|
extern int register_android_hardware_SensorManager(JNIEnv *env);
|
|
|
|
extern int register_android_media_AudioRecord(JNIEnv *env);
|
|
extern int register_android_media_AudioSystem(JNIEnv *env);
|
|
extern int register_android_media_AudioTrack(JNIEnv *env);
|
|
extern int register_android_media_JetPlayer(JNIEnv *env);
|
|
extern int register_android_media_ToneGenerator(JNIEnv *env);
|
|
|
|
extern int register_android_message_digest_sha1(JNIEnv *env);
|
|
|
|
extern int register_android_util_FloatMath(JNIEnv* env);
|
|
|
|
namespace android {
|
|
|
|
/*
|
|
* JNI-based registration functions. Note these are properly contained in
|
|
* namespace android.
|
|
*/
|
|
extern int register_android_content_AssetManager(JNIEnv* env);
|
|
extern int register_android_util_EventLog(JNIEnv* env);
|
|
extern int register_android_util_Log(JNIEnv* env);
|
|
extern int register_android_content_StringBlock(JNIEnv* env);
|
|
extern int register_android_content_XmlBlock(JNIEnv* env);
|
|
extern int register_android_emoji_EmojiFactory(JNIEnv* env);
|
|
extern int register_android_graphics_Canvas(JNIEnv* env);
|
|
extern int register_android_graphics_ColorFilter(JNIEnv* env);
|
|
extern int register_android_graphics_DrawFilter(JNIEnv* env);
|
|
extern int register_android_graphics_Matrix(JNIEnv* env);
|
|
extern int register_android_graphics_Paint(JNIEnv* env);
|
|
extern int register_android_graphics_Path(JNIEnv* env);
|
|
extern int register_android_graphics_PathMeasure(JNIEnv* env);
|
|
extern int register_android_graphics_Picture(JNIEnv*);
|
|
extern int register_android_graphics_PorterDuff(JNIEnv* env);
|
|
extern int register_android_graphics_Rasterizer(JNIEnv* env);
|
|
extern int register_android_graphics_Xfermode(JNIEnv* env);
|
|
extern int register_android_graphics_PixelFormat(JNIEnv* env);
|
|
extern int register_com_android_internal_graphics_NativeUtils(JNIEnv *env);
|
|
extern int register_android_view_Display(JNIEnv* env);
|
|
extern int register_android_view_Surface(JNIEnv* env);
|
|
extern int register_android_view_ViewRoot(JNIEnv* env);
|
|
extern int register_android_database_CursorWindow(JNIEnv* env);
|
|
extern int register_android_database_SQLiteDatabase(JNIEnv* env);
|
|
extern int register_android_database_SQLiteDebug(JNIEnv* env);
|
|
extern int register_android_database_SQLiteProgram(JNIEnv* env);
|
|
extern int register_android_database_SQLiteQuery(JNIEnv* env);
|
|
extern int register_android_database_SQLiteStatement(JNIEnv* env);
|
|
extern int register_android_debug_JNITest(JNIEnv* env);
|
|
extern int register_android_nio_utils(JNIEnv* env);
|
|
extern int register_android_pim_EventRecurrence(JNIEnv* env);
|
|
extern int register_android_text_format_Time(JNIEnv* env);
|
|
extern int register_android_os_Debug(JNIEnv* env);
|
|
extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
|
|
extern int register_android_os_Power(JNIEnv *env);
|
|
extern int register_android_os_StatFs(JNIEnv *env);
|
|
extern int register_android_os_SystemProperties(JNIEnv *env);
|
|
extern int register_android_os_Hardware(JNIEnv* env);
|
|
extern int register_android_os_Exec(JNIEnv *env);
|
|
extern int register_android_os_SystemClock(JNIEnv* env);
|
|
extern int register_android_os_FileObserver(JNIEnv *env);
|
|
extern int register_android_os_FileUtils(JNIEnv *env);
|
|
extern int register_android_os_UEventObserver(JNIEnv* env);
|
|
extern int register_android_os_MemoryFile(JNIEnv* env);
|
|
extern int register_android_net_LocalSocketImpl(JNIEnv* env);
|
|
extern int register_android_net_NetworkUtils(JNIEnv* env);
|
|
extern int register_android_net_wifi_WifiManager(JNIEnv* env);
|
|
extern int register_android_security_Md5MessageDigest(JNIEnv *env);
|
|
extern int register_android_text_AndroidCharacter(JNIEnv *env);
|
|
extern int register_android_text_KeyCharacterMap(JNIEnv *env);
|
|
extern int register_android_opengl_classes(JNIEnv *env);
|
|
extern int register_android_bluetooth_Database(JNIEnv* env);
|
|
extern int register_android_bluetooth_HeadsetBase(JNIEnv* env);
|
|
extern int register_android_bluetooth_BluetoothAudioGateway(JNIEnv* env);
|
|
extern int register_android_bluetooth_RfcommSocket(JNIEnv *env);
|
|
extern int register_android_bluetooth_ScoSocket(JNIEnv *env);
|
|
extern int register_android_server_BluetoothDeviceService(JNIEnv* env);
|
|
extern int register_android_server_BluetoothEventLoop(JNIEnv *env);
|
|
extern int register_android_server_BluetoothA2dpService(JNIEnv* env);
|
|
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
|
|
extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env);
|
|
extern int register_android_util_Base64(JNIEnv* env);
|
|
extern int register_android_location_GpsLocationProvider(JNIEnv* env);
|
|
|
|
static AndroidRuntime* gCurRuntime = NULL;
|
|
|
|
static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
|
|
{
|
|
if (jniThrowException(env, exc, msg) != 0)
|
|
assert(false);
|
|
}
|
|
|
|
/*
|
|
* Code written in the Java Programming Language calls here from main().
|
|
*/
|
|
static void com_android_internal_os_RuntimeInit_finishInit(JNIEnv* env, jobject clazz)
|
|
{
|
|
gCurRuntime->onStarted();
|
|
}
|
|
|
|
static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
|
|
{
|
|
gCurRuntime->onZygoteInit();
|
|
}
|
|
|
|
static jint com_android_internal_os_RuntimeInit_isComputerOn(JNIEnv* env, jobject clazz)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static void com_android_internal_os_RuntimeInit_turnComputerOn(JNIEnv* env, jobject clazz)
|
|
{
|
|
}
|
|
|
|
static jint com_android_internal_os_RuntimeInit_getQwertyKeyboard(JNIEnv* env, jobject clazz)
|
|
{
|
|
char* value = getenv("qwerty");
|
|
if (value != NULL && strcmp(value, "true") == 0) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* JNI registration.
|
|
*/
|
|
static JNINativeMethod gMethods[] = {
|
|
{ "finishInit", "()V",
|
|
(void*) com_android_internal_os_RuntimeInit_finishInit },
|
|
{ "zygoteInitNative", "()V",
|
|
(void*) com_android_internal_os_RuntimeInit_zygoteInit },
|
|
{ "isComputerOn", "()I",
|
|
(void*) com_android_internal_os_RuntimeInit_isComputerOn },
|
|
{ "turnComputerOn", "()V",
|
|
(void*) com_android_internal_os_RuntimeInit_turnComputerOn },
|
|
{ "getQwertyKeyboard", "()I",
|
|
(void*) com_android_internal_os_RuntimeInit_getQwertyKeyboard },
|
|
};
|
|
|
|
int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
|
|
{
|
|
return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
|
|
gMethods, NELEM(gMethods));
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
|
|
/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
|
|
|
|
|
|
AndroidRuntime::AndroidRuntime()
|
|
{
|
|
SkGraphics::Init();
|
|
// this sets our preference for 16bit images during decode
|
|
// in case the src is opaque and 24bit
|
|
SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
|
|
|
|
// Pre-allocate enough space to hold a fair number of options.
|
|
mOptions.setCapacity(20);
|
|
|
|
assert(gCurRuntime == NULL); // one per process
|
|
gCurRuntime = this;
|
|
}
|
|
|
|
AndroidRuntime::~AndroidRuntime()
|
|
{
|
|
SkGraphics::Term();
|
|
}
|
|
|
|
/*
|
|
* Register native methods using JNI.
|
|
*/
|
|
/*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,
|
|
const char* className, const JNINativeMethod* gMethods, int numMethods)
|
|
{
|
|
return jniRegisterNativeMethods(env, className, gMethods, numMethods);
|
|
}
|
|
|
|
/*
|
|
* Call a static Java Programming Language function that takes no arguments and returns void.
|
|
*/
|
|
status_t AndroidRuntime::callStatic(const char* className, const char* methodName)
|
|
{
|
|
JNIEnv* env;
|
|
jclass clazz;
|
|
jmethodID methodId;
|
|
|
|
env = getJNIEnv();
|
|
if (env == NULL)
|
|
return UNKNOWN_ERROR;
|
|
|
|
clazz = findClass(env, className);
|
|
if (clazz == NULL) {
|
|
LOGE("ERROR: could not find class '%s'\n", className);
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
methodId = env->GetStaticMethodID(clazz, methodName, "()V");
|
|
if (methodId == NULL) {
|
|
LOGE("ERROR: could not find method %s.%s\n", className, methodName);
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
|
|
env->CallStaticVoidMethod(clazz, methodId);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
status_t AndroidRuntime::callMain(
|
|
const char* className, int argc, const char* const argv[])
|
|
{
|
|
JNIEnv* env;
|
|
jclass clazz;
|
|
jmethodID methodId;
|
|
|
|
env = getJNIEnv();
|
|
if (env == NULL)
|
|
return UNKNOWN_ERROR;
|
|
|
|
clazz = findClass(env, className);
|
|
if (clazz == NULL) {
|
|
LOGE("ERROR: could not find class '%s'\n", className);
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
|
|
methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
|
|
if (methodId == NULL) {
|
|
LOGE("ERROR: could not find method %s.main(String[])\n", className);
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
|
|
/*
|
|
* We want to call main() with a String array with our arguments in it.
|
|
* Create an array and populate it.
|
|
*/
|
|
jclass stringClass;
|
|
jobjectArray strArray;
|
|
|
|
stringClass = env->FindClass("java/lang/String");
|
|
strArray = env->NewObjectArray(argc, stringClass, NULL);
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
jstring argStr = env->NewStringUTF(argv[i]);
|
|
env->SetObjectArrayElement(strArray, i, argStr);
|
|
}
|
|
|
|
env->CallStaticVoidMethod(clazz, methodId, strArray);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/*
|
|
* Find the named class.
|
|
*/
|
|
jclass AndroidRuntime::findClass(JNIEnv* env, const char* className)
|
|
{
|
|
char* convName = NULL;
|
|
|
|
if (env->ExceptionCheck()) {
|
|
LOGE("ERROR: exception pending on entry to findClass()\n");
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* JNI FindClass uses class names with slashes, but ClassLoader.loadClass
|
|
* uses the dotted "binary name" format. We don't need to convert the
|
|
* name with the new approach.
|
|
*/
|
|
#if 0
|
|
/* (convName only created if necessary -- use className) */
|
|
for (char* cp = const_cast<char*>(className); *cp != '\0'; cp++) {
|
|
if (*cp == '.') {
|
|
if (convName == NULL) {
|
|
convName = strdup(className);
|
|
cp = convName + (cp-className);
|
|
className = convName;
|
|
}
|
|
*cp = '/';
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* This is a little awkward because the JNI FindClass call uses the
|
|
* class loader associated with the native method we're executing in.
|
|
* Because this native method is part of a "boot" class, JNI doesn't
|
|
* look for the class in CLASSPATH, which unfortunately is a likely
|
|
* location for it. (Had we issued the FindClass call before calling
|
|
* into the VM -- at which point there isn't a native method frame on
|
|
* the stack -- the VM would have checked CLASSPATH. We have to do
|
|
* this because we call into Java Programming Language code and
|
|
* bounce back out.)
|
|
*
|
|
* JNI lacks a "find class in a specific class loader" operation, so we
|
|
* have to do things the hard way.
|
|
*/
|
|
jclass cls = NULL;
|
|
//cls = env->FindClass(className);
|
|
|
|
jclass javaLangClassLoader;
|
|
jmethodID getSystemClassLoader, loadClass;
|
|
jobject systemClassLoader;
|
|
jstring strClassName;
|
|
|
|
/* find the "system" class loader; none of this is expected to fail */
|
|
javaLangClassLoader = env->FindClass("java/lang/ClassLoader");
|
|
assert(javaLangClassLoader != NULL);
|
|
getSystemClassLoader = env->GetStaticMethodID(javaLangClassLoader,
|
|
"getSystemClassLoader", "()Ljava/lang/ClassLoader;");
|
|
loadClass = env->GetMethodID(javaLangClassLoader,
|
|
"loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
|
|
assert(getSystemClassLoader != NULL && loadClass != NULL);
|
|
systemClassLoader = env->CallStaticObjectMethod(javaLangClassLoader,
|
|
getSystemClassLoader);
|
|
assert(systemClassLoader != NULL);
|
|
|
|
/* create an object for the class name string; alloc could fail */
|
|
strClassName = env->NewStringUTF(className);
|
|
if (env->ExceptionCheck()) {
|
|
LOGE("ERROR: unable to convert '%s' to string\n", className);
|
|
goto bail;
|
|
}
|
|
LOGV("system class loader is %p, loading %p (%s)\n",
|
|
systemClassLoader, strClassName, className);
|
|
|
|
/* try to find the named class */
|
|
cls = (jclass) env->CallObjectMethod(systemClassLoader, loadClass,
|
|
strClassName);
|
|
if (env->ExceptionCheck()) {
|
|
LOGE("ERROR: unable to load class '%s' from %p\n",
|
|
className, systemClassLoader);
|
|
cls = NULL;
|
|
goto bail;
|
|
}
|
|
|
|
bail:
|
|
free(convName);
|
|
return cls;
|
|
}
|
|
|
|
/*
|
|
* The VM calls this through the "exit" hook.
|
|
*/
|
|
static void runtime_exit(int code)
|
|
{
|
|
gCurRuntime->onExit(code);
|
|
exit(code);
|
|
}
|
|
|
|
/*
|
|
* The VM calls this through the "vfprintf" hook.
|
|
*
|
|
* We ignore "fp" and just write the results to the log file.
|
|
*/
|
|
static void runtime_vfprintf(FILE* fp, const char* format, va_list ap)
|
|
{
|
|
LOG_PRI_VA(ANDROID_LOG_INFO, "vm-printf", format, ap);
|
|
}
|
|
|
|
|
|
/**
|
|
* Add VM arguments to the to-be-executed VM
|
|
* Stops at first non '-' argument (also stops at an argument of '--')
|
|
* Returns the number of args consumed
|
|
*/
|
|
int AndroidRuntime::addVmArguments(int argc, const char* const argv[])
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i<argc; i++) {
|
|
if (argv[i][0] != '-') {
|
|
return i;
|
|
}
|
|
if (argv[i][1] == '-' && argv[i][2] == 0) {
|
|
return i+1;
|
|
}
|
|
|
|
JavaVMOption opt;
|
|
memset(&opt, 0, sizeof(opt));
|
|
opt.optionString = (char*)argv[i];
|
|
mOptions.add(opt);
|
|
}
|
|
return i;
|
|
}
|
|
|
|
static int hasDir(const char* dir)
|
|
{
|
|
struct stat s;
|
|
int res = stat(dir, &s);
|
|
if (res == 0) {
|
|
return S_ISDIR(s.st_mode);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* We just want failed write() calls to just return with an error.
|
|
*/
|
|
static void blockSigpipe()
|
|
{
|
|
sigset_t mask;
|
|
|
|
sigemptyset(&mask);
|
|
sigaddset(&mask, SIGPIPE);
|
|
if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
|
|
LOGW("WARNING: SIGPIPE not blocked\n");
|
|
}
|
|
|
|
/*
|
|
* Read the persistent locale.
|
|
*/
|
|
static void readLocale(char* language, char* region)
|
|
{
|
|
char propLang[PROPERTY_VALUE_MAX], propRegn[PROPERTY_VALUE_MAX];
|
|
|
|
property_get("persist.sys.language", propLang, "");
|
|
property_get("persist.sys.country", propRegn, "");
|
|
if (*propLang == 0 && *propRegn == 0) {
|
|
/* Set to ro properties, default is en_US */
|
|
property_get("ro.product.locale.language", propLang, "en");
|
|
property_get("ro.product.locale.region", propRegn, "US");
|
|
}
|
|
strncat(language, propLang, 2);
|
|
strncat(region, propRegn, 2);
|
|
//LOGD("language=%s region=%s\n", language, region);
|
|
}
|
|
|
|
void AndroidRuntime::start(const char* className, const bool startSystemServer)
|
|
{
|
|
LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
|
|
|
|
JNIEnv* env;
|
|
JavaVMInitArgs initArgs;
|
|
JavaVMOption opt;
|
|
char propBuf[PROPERTY_VALUE_MAX];
|
|
char stackTraceFileBuf[PROPERTY_VALUE_MAX];
|
|
char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
|
|
char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
|
|
char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
|
|
char* stackTraceFile = NULL;
|
|
char* slashClassName = NULL;
|
|
char* cp;
|
|
bool checkJni = false;
|
|
bool logStdio = false;
|
|
enum { kEMDefault, kEMIntPortable, kEMIntFast } executionMode = kEMDefault;
|
|
|
|
blockSigpipe();
|
|
|
|
/*
|
|
* 'startSystemServer == true' means runtime is obslete and not run from
|
|
* init.rc anymore, so we print out the boot start event here.
|
|
*/
|
|
if (startSystemServer) {
|
|
/* track our progress through the boot sequence */
|
|
const int LOG_BOOT_PROGRESS_START = 3000;
|
|
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
|
|
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
|
|
}
|
|
|
|
property_get("dalvik.vm.checkjni", propBuf, "");
|
|
if (strcmp(propBuf, "true") == 0) {
|
|
checkJni = true;
|
|
} else if (strcmp(propBuf, "false") != 0) {
|
|
/* property is neither true nor false; fall back on kernel parameter */
|
|
property_get("ro.kernel.android.checkjni", propBuf, "");
|
|
if (propBuf[0] == '1') {
|
|
checkJni = true;
|
|
}
|
|
}
|
|
|
|
property_get("dalvik.vm.execution-mode", propBuf, "");
|
|
if (strcmp(propBuf, "int:portable") == 0) {
|
|
executionMode = kEMIntPortable;
|
|
} else if (strcmp(propBuf, "int:fast") == 0) {
|
|
executionMode = kEMIntFast;
|
|
}
|
|
|
|
property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");
|
|
|
|
property_get("log.redirect-stdio", propBuf, "");
|
|
if (strcmp(propBuf, "true") == 0) {
|
|
logStdio = true;
|
|
}
|
|
|
|
strcpy(enableAssertBuf, "-ea:");
|
|
property_get("dalvik.vm.enableassertions", enableAssertBuf+4, "");
|
|
|
|
strcpy(jniOptsBuf, "-Xjniopts:");
|
|
property_get("dalvik.vm.jniopts", jniOptsBuf+10, "");
|
|
|
|
const char* rootDir = getenv("ANDROID_ROOT");
|
|
if (rootDir == NULL) {
|
|
rootDir = "/system";
|
|
if (!hasDir("/system")) {
|
|
LOG_FATAL("No root directory specified, and /android does not exist.");
|
|
return;
|
|
}
|
|
setenv("ANDROID_ROOT", rootDir, 1);
|
|
}
|
|
|
|
const char* kernelHack = getenv("LD_ASSUME_KERNEL");
|
|
//LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
|
|
|
|
/* route exit() to our handler */
|
|
opt.extraInfo = (void*) runtime_exit;
|
|
opt.optionString = "exit";
|
|
mOptions.add(opt);
|
|
|
|
/* route fprintf() to our handler */
|
|
opt.extraInfo = (void*) runtime_vfprintf;
|
|
opt.optionString = "vfprintf";
|
|
mOptions.add(opt);
|
|
|
|
opt.extraInfo = NULL;
|
|
|
|
/* enable verbose; standard options are { jni, gc, class } */
|
|
//options[curOpt++].optionString = "-verbose:jni";
|
|
opt.optionString = "-verbose:gc";
|
|
mOptions.add(opt);
|
|
//options[curOpt++].optionString = "-verbose:class";
|
|
|
|
#ifdef CUSTOM_RUNTIME_HEAP_MAX
|
|
#define __make_max_heap_opt(val) #val
|
|
#define _make_max_heap_opt(val) "-Xmx" __make_max_heap_opt(val)
|
|
opt.optionString = _make_max_heap_opt(CUSTOM_RUNTIME_HEAP_MAX);
|
|
#undef __make_max_heap_opt
|
|
#undef _make_max_heap_opt
|
|
#else
|
|
/* limit memory use to 16MB */
|
|
opt.optionString = "-Xmx16m";
|
|
#endif
|
|
mOptions.add(opt);
|
|
|
|
/*
|
|
* Enable or disable dexopt features, such as bytecode verification and
|
|
* calculation of register maps for precise GC.
|
|
*/
|
|
property_get("dalvik.vm.dexopt-flags", dexoptFlagsBuf, "");
|
|
if (dexoptFlagsBuf[0] != '\0') {
|
|
const char* opc;
|
|
const char* val;
|
|
|
|
opc = strstr(dexoptFlagsBuf, "v="); /* verification */
|
|
if (opc != NULL) {
|
|
switch (*(opc+2)) {
|
|
case 'n': val = "-Xverify:none"; break;
|
|
case 'r': val = "-Xverify:remote"; break;
|
|
case 'a': val = "-Xverify:all"; break;
|
|
default: val = NULL; break;
|
|
}
|
|
|
|
if (val != NULL) {
|
|
opt.optionString = val;
|
|
mOptions.add(opt);
|
|
}
|
|
}
|
|
|
|
opc = strstr(dexoptFlagsBuf, "o="); /* optimization */
|
|
if (opc != NULL) {
|
|
switch (*(opc+2)) {
|
|
case 'n': val = "-Xdexopt:none"; break;
|
|
case 'v': val = "-Xdexopt:verified"; break;
|
|
case 'a': val = "-Xdexopt:all"; break;
|
|
default: val = NULL; break;
|
|
}
|
|
|
|
if (val != NULL) {
|
|
opt.optionString = val;
|
|
mOptions.add(opt);
|
|
}
|
|
}
|
|
|
|
opc = strstr(dexoptFlagsBuf, "m=y"); /* register map */
|
|
if (opc != NULL) {
|
|
opt.optionString = "-Xgenregmap";
|
|
mOptions.add(opt);
|
|
}
|
|
}
|
|
|
|
/* enable debugging; set suspend=y to pause during VM init */
|
|
#ifdef HAVE_ANDROID_OS
|
|
/* use android ADB transport */
|
|
opt.optionString =
|
|
"-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
|
|
#else
|
|
/* use TCP socket; address=0 means start at port 8000 and probe up */
|
|
LOGI("Using TCP socket for JDWP\n");
|
|
opt.optionString =
|
|
"-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";
|
|
#endif
|
|
mOptions.add(opt);
|
|
|
|
char enableDPBuf[sizeof("-Xdeadlockpredict:") + PROPERTY_VALUE_MAX];
|
|
property_get("dalvik.vm.deadlock-predict", propBuf, "");
|
|
if (strlen(propBuf) > 0) {
|
|
strcpy(enableDPBuf, "-Xdeadlockpredict:");
|
|
strcat(enableDPBuf, propBuf);
|
|
opt.optionString = enableDPBuf;
|
|
mOptions.add(opt);
|
|
}
|
|
|
|
LOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
|
|
if (checkJni) {
|
|
/* extended JNI checking */
|
|
opt.optionString = "-Xcheck:jni";
|
|
mOptions.add(opt);
|
|
|
|
/* set a cap on JNI global references */
|
|
opt.optionString = "-Xjnigreflimit:2000";
|
|
mOptions.add(opt);
|
|
|
|
/* with -Xcheck:jni, this provides a JNI function call trace */
|
|
//opt.optionString = "-verbose:jni";
|
|
//mOptions.add(opt);
|
|
}
|
|
if (executionMode == kEMIntPortable) {
|
|
opt.optionString = "-Xint:portable";
|
|
mOptions.add(opt);
|
|
} else if (executionMode == kEMIntFast) {
|
|
opt.optionString = "-Xint:fast";
|
|
mOptions.add(opt);
|
|
}
|
|
if (logStdio) {
|
|
/* convert stdout/stderr to log messages */
|
|
opt.optionString = "-Xlog-stdio";
|
|
mOptions.add(opt);
|
|
}
|
|
|
|
if (enableAssertBuf[4] != '\0') {
|
|
/* accept "all" to mean "all classes and packages" */
|
|
if (strcmp(enableAssertBuf+4, "all") == 0)
|
|
enableAssertBuf[3] = '\0';
|
|
LOGI("Assertions enabled: '%s'\n", enableAssertBuf);
|
|
opt.optionString = enableAssertBuf;
|
|
mOptions.add(opt);
|
|
} else {
|
|
LOGV("Assertions disabled\n");
|
|
}
|
|
|
|
if (jniOptsBuf[10] != '\0') {
|
|
LOGI("JNI options: '%s'\n", jniOptsBuf);
|
|
opt.optionString = jniOptsBuf;
|
|
mOptions.add(opt);
|
|
}
|
|
|
|
if (stackTraceFileBuf[0] != '\0') {
|
|
static const char* stfOptName = "-Xstacktracefile:";
|
|
|
|
stackTraceFile = (char*) malloc(strlen(stfOptName) +
|
|
strlen(stackTraceFileBuf) +1);
|
|
strcpy(stackTraceFile, stfOptName);
|
|
strcat(stackTraceFile, stackTraceFileBuf);
|
|
opt.optionString = stackTraceFile;
|
|
mOptions.add(opt);
|
|
}
|
|
|
|
/* Set the properties for locale */
|
|
{
|
|
char langOption[sizeof("-Duser.language=") + 3];
|
|
char regionOption[sizeof("-Duser.region=") + 3];
|
|
strcpy(langOption, "-Duser.language=");
|
|
strcpy(regionOption, "-Duser.region=");
|
|
readLocale(langOption, regionOption);
|
|
opt.extraInfo = NULL;
|
|
opt.optionString = langOption;
|
|
mOptions.add(opt);
|
|
opt.optionString = regionOption;
|
|
mOptions.add(opt);
|
|
}
|
|
|
|
/*
|
|
* We don't have /tmp on the device, but we often have an SD card. Apps
|
|
* shouldn't use this, but some test suites might want to exercise it.
|
|
*/
|
|
opt.optionString = "-Djava.io.tmpdir=/sdcard";
|
|
mOptions.add(opt);
|
|
|
|
initArgs.version = JNI_VERSION_1_4;
|
|
initArgs.options = mOptions.editArray();
|
|
initArgs.nOptions = mOptions.size();
|
|
initArgs.ignoreUnrecognized = JNI_FALSE;
|
|
|
|
/*
|
|
* Initialize the VM.
|
|
*
|
|
* The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
|
|
* If this call succeeds, the VM is ready, and we can start issuing
|
|
* JNI calls.
|
|
*/
|
|
if (JNI_CreateJavaVM(&mJavaVM, &env, &initArgs) < 0) {
|
|
LOGE("JNI_CreateJavaVM failed\n");
|
|
goto bail;
|
|
}
|
|
|
|
/*
|
|
* Register android functions.
|
|
*/
|
|
if (startReg(env) < 0) {
|
|
LOGE("Unable to register all android natives\n");
|
|
goto bail;
|
|
}
|
|
|
|
/*
|
|
* We want to call main() with a String array with arguments in it.
|
|
* At present we only have one argument, the class name. Create an
|
|
* array to hold it.
|
|
*/
|
|
jclass stringClass;
|
|
jobjectArray strArray;
|
|
jstring classNameStr;
|
|
jstring startSystemServerStr;
|
|
|
|
stringClass = env->FindClass("java/lang/String");
|
|
assert(stringClass != NULL);
|
|
strArray = env->NewObjectArray(2, stringClass, NULL);
|
|
assert(strArray != NULL);
|
|
classNameStr = env->NewStringUTF(className);
|
|
assert(classNameStr != NULL);
|
|
env->SetObjectArrayElement(strArray, 0, classNameStr);
|
|
startSystemServerStr = env->NewStringUTF(startSystemServer ?
|
|
"true" : "false");
|
|
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
|
|
|
|
/*
|
|
* Start VM. This thread becomes the main thread of the VM, and will
|
|
* not return until the VM exits.
|
|
*/
|
|
jclass startClass;
|
|
jmethodID startMeth;
|
|
|
|
slashClassName = strdup(className);
|
|
for (cp = slashClassName; *cp != '\0'; cp++)
|
|
if (*cp == '.')
|
|
*cp = '/';
|
|
|
|
startClass = env->FindClass(slashClassName);
|
|
if (startClass == NULL) {
|
|
LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
|
|
/* keep going */
|
|
} else {
|
|
startMeth = env->GetStaticMethodID(startClass, "main",
|
|
"([Ljava/lang/String;)V");
|
|
if (startMeth == NULL) {
|
|
LOGE("JavaVM unable to find main() in '%s'\n", className);
|
|
/* keep going */
|
|
} else {
|
|
env->CallStaticVoidMethod(startClass, startMeth, strArray);
|
|
|
|
#if 0
|
|
if (env->ExceptionCheck())
|
|
threadExitUncaughtException(env);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
LOGD("Shutting down VM\n");
|
|
if (mJavaVM->DetachCurrentThread() != JNI_OK)
|
|
LOGW("Warning: unable to detach main thread\n");
|
|
if (mJavaVM->DestroyJavaVM() != 0)
|
|
LOGW("Warning: VM did not shut down cleanly\n");
|
|
|
|
bail:
|
|
free(slashClassName);
|
|
free(stackTraceFile);
|
|
}
|
|
|
|
void AndroidRuntime::start()
|
|
{
|
|
start("com.android.internal.os.RuntimeInit",
|
|
false /* Don't start the system server */);
|
|
}
|
|
|
|
void AndroidRuntime::onExit(int code)
|
|
{
|
|
LOGI("AndroidRuntime onExit calling exit(%d)", code);
|
|
exit(code);
|
|
}
|
|
|
|
/*
|
|
* Get the JNIEnv pointer for this thread.
|
|
*
|
|
* Returns NULL if the slot wasn't allocated or populated.
|
|
*/
|
|
/*static*/ JNIEnv* AndroidRuntime::getJNIEnv()
|
|
{
|
|
JNIEnv* env;
|
|
JavaVM* vm = AndroidRuntime::getJavaVM();
|
|
assert(vm != NULL);
|
|
|
|
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
|
|
return NULL;
|
|
return env;
|
|
}
|
|
|
|
/*
|
|
* Makes the current thread visible to the VM.
|
|
*
|
|
* The JNIEnv pointer returned is only valid for the current thread, and
|
|
* thus must be tucked into thread-local storage.
|
|
*/
|
|
static int javaAttachThread(const char* threadName, JNIEnv** pEnv)
|
|
{
|
|
JavaVMAttachArgs args;
|
|
JavaVM* vm;
|
|
jint result;
|
|
|
|
vm = AndroidRuntime::getJavaVM();
|
|
assert(vm != NULL);
|
|
|
|
args.version = JNI_VERSION_1_4;
|
|
args.name = (char*) threadName;
|
|
args.group = NULL;
|
|
|
|
result = vm->AttachCurrentThread(pEnv, (void*) &args);
|
|
if (result != JNI_OK)
|
|
LOGE("ERROR: thread attach failed\n");
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* Detach the current thread from the set visible to the VM.
|
|
*/
|
|
static int javaDetachThread(void)
|
|
{
|
|
JavaVM* vm;
|
|
jint result;
|
|
|
|
vm = AndroidRuntime::getJavaVM();
|
|
assert(vm != NULL);
|
|
|
|
result = vm->DetachCurrentThread();
|
|
if (result != JNI_OK)
|
|
LOGE("ERROR: thread detach failed\n");
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* When starting a native thread that will be visible from the VM, we
|
|
* bounce through this to get the right attach/detach action.
|
|
* Note that this function calls free(args)
|
|
*/
|
|
/*static*/ int AndroidRuntime::javaThreadShell(void* args) {
|
|
void* start = ((void**)args)[0];
|
|
void* userData = ((void **)args)[1];
|
|
char* name = (char*) ((void **)args)[2]; // we own this storage
|
|
free(args);
|
|
JNIEnv* env;
|
|
int result;
|
|
|
|
/* hook us into the VM */
|
|
if (javaAttachThread(name, &env) != JNI_OK)
|
|
return -1;
|
|
|
|
/* start the thread running */
|
|
result = (*(android_thread_func_t)start)(userData);
|
|
|
|
/* unhook us */
|
|
javaDetachThread();
|
|
free(name);
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* This is invoked from androidCreateThreadEtc() via the callback
|
|
* set with androidSetCreateThreadFunc().
|
|
*
|
|
* We need to create the new thread in such a way that it gets hooked
|
|
* into the VM before it really starts executing.
|
|
*/
|
|
/*static*/ int AndroidRuntime::javaCreateThreadEtc(
|
|
android_thread_func_t entryFunction,
|
|
void* userData,
|
|
const char* threadName,
|
|
int32_t threadPriority,
|
|
size_t threadStackSize,
|
|
android_thread_id_t* threadId)
|
|
{
|
|
void** args = (void**) malloc(3 * sizeof(void*)); // javaThreadShell must free
|
|
int result;
|
|
|
|
assert(threadName != NULL);
|
|
|
|
args[0] = (void*) entryFunction;
|
|
args[1] = userData;
|
|
args[2] = (void*) strdup(threadName); // javaThreadShell must free
|
|
|
|
result = androidCreateRawThreadEtc(AndroidRuntime::javaThreadShell, args,
|
|
threadName, threadPriority, threadStackSize, threadId);
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* Create a thread that is visible from the VM.
|
|
*
|
|
* This is called from elsewhere in the library.
|
|
*/
|
|
/*static*/ void AndroidRuntime::createJavaThread(const char* name,
|
|
void (*start)(void *), void* arg)
|
|
{
|
|
javaCreateThreadEtc((android_thread_func_t) start, arg, name,
|
|
ANDROID_PRIORITY_DEFAULT, 0, NULL);
|
|
}
|
|
|
|
#if 0
|
|
static void quickTest(void* arg)
|
|
{
|
|
const char* str = (const char*) arg;
|
|
|
|
printf("In quickTest: %s\n", str);
|
|
}
|
|
#endif
|
|
|
|
#ifdef NDEBUG
|
|
#define REG_JNI(name) { name }
|
|
struct RegJNIRec {
|
|
int (*mProc)(JNIEnv*);
|
|
};
|
|
#else
|
|
#define REG_JNI(name) { name, #name }
|
|
struct RegJNIRec {
|
|
int (*mProc)(JNIEnv*);
|
|
const char* mName;
|
|
};
|
|
#endif
|
|
|
|
typedef void (*RegJAMProc)();
|
|
|
|
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
|
|
{
|
|
for (size_t i = 0; i < count; i++) {
|
|
if (array[i].mProc(env) < 0) {
|
|
#ifndef NDEBUG
|
|
LOGD("----------!!! %s failed to load\n", array[i].mName);
|
|
#endif
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void register_jam_procs(const RegJAMProc array[], size_t count)
|
|
{
|
|
for (size_t i = 0; i < count; i++) {
|
|
array[i]();
|
|
}
|
|
}
|
|
|
|
static const RegJNIRec gRegJNI[] = {
|
|
REG_JNI(register_android_debug_JNITest),
|
|
REG_JNI(register_com_android_internal_os_RuntimeInit),
|
|
REG_JNI(register_android_os_SystemClock),
|
|
REG_JNI(register_android_util_EventLog),
|
|
REG_JNI(register_android_util_Log),
|
|
REG_JNI(register_android_util_FloatMath),
|
|
REG_JNI(register_android_text_format_Time),
|
|
REG_JNI(register_android_pim_EventRecurrence),
|
|
REG_JNI(register_android_content_AssetManager),
|
|
REG_JNI(register_android_content_StringBlock),
|
|
REG_JNI(register_android_content_XmlBlock),
|
|
REG_JNI(register_android_emoji_EmojiFactory),
|
|
REG_JNI(register_android_security_Md5MessageDigest),
|
|
REG_JNI(register_android_text_AndroidCharacter),
|
|
REG_JNI(register_android_text_KeyCharacterMap),
|
|
REG_JNI(register_android_os_Process),
|
|
REG_JNI(register_android_os_Binder),
|
|
REG_JNI(register_android_os_Hardware),
|
|
REG_JNI(register_android_view_Display),
|
|
REG_JNI(register_android_nio_utils),
|
|
REG_JNI(register_android_graphics_PixelFormat),
|
|
REG_JNI(register_android_graphics_Graphics),
|
|
REG_JNI(register_android_view_Surface),
|
|
REG_JNI(register_android_view_ViewRoot),
|
|
REG_JNI(register_com_google_android_gles_jni_EGLImpl),
|
|
REG_JNI(register_com_google_android_gles_jni_GLImpl),
|
|
REG_JNI(register_android_opengl_jni_GLES10),
|
|
REG_JNI(register_android_opengl_jni_GLES10Ext),
|
|
REG_JNI(register_android_opengl_jni_GLES11),
|
|
REG_JNI(register_android_opengl_jni_GLES11Ext),
|
|
|
|
REG_JNI(register_android_graphics_Bitmap),
|
|
REG_JNI(register_android_graphics_BitmapFactory),
|
|
REG_JNI(register_android_graphics_Camera),
|
|
REG_JNI(register_android_graphics_Canvas),
|
|
REG_JNI(register_android_graphics_ColorFilter),
|
|
REG_JNI(register_android_graphics_DrawFilter),
|
|
REG_JNI(register_android_graphics_Interpolator),
|
|
REG_JNI(register_android_graphics_LayerRasterizer),
|
|
REG_JNI(register_android_graphics_MaskFilter),
|
|
REG_JNI(register_android_graphics_Matrix),
|
|
REG_JNI(register_android_graphics_Movie),
|
|
REG_JNI(register_android_graphics_NinePatch),
|
|
REG_JNI(register_android_graphics_Paint),
|
|
REG_JNI(register_android_graphics_Path),
|
|
REG_JNI(register_android_graphics_PathMeasure),
|
|
REG_JNI(register_android_graphics_PathEffect),
|
|
REG_JNI(register_android_graphics_Picture),
|
|
REG_JNI(register_android_graphics_PorterDuff),
|
|
REG_JNI(register_android_graphics_Rasterizer),
|
|
REG_JNI(register_android_graphics_Region),
|
|
REG_JNI(register_android_graphics_Shader),
|
|
REG_JNI(register_android_graphics_Typeface),
|
|
REG_JNI(register_android_graphics_Xfermode),
|
|
REG_JNI(register_com_android_internal_graphics_NativeUtils),
|
|
|
|
REG_JNI(register_android_database_CursorWindow),
|
|
REG_JNI(register_android_database_SQLiteDatabase),
|
|
REG_JNI(register_android_database_SQLiteDebug),
|
|
REG_JNI(register_android_database_SQLiteProgram),
|
|
REG_JNI(register_android_database_SQLiteQuery),
|
|
REG_JNI(register_android_database_SQLiteStatement),
|
|
REG_JNI(register_android_os_Debug),
|
|
REG_JNI(register_android_os_Exec),
|
|
REG_JNI(register_android_os_FileObserver),
|
|
REG_JNI(register_android_os_FileUtils),
|
|
REG_JNI(register_android_os_ParcelFileDescriptor),
|
|
REG_JNI(register_android_os_Power),
|
|
REG_JNI(register_android_os_StatFs),
|
|
REG_JNI(register_android_os_SystemProperties),
|
|
REG_JNI(register_android_os_UEventObserver),
|
|
REG_JNI(register_android_net_LocalSocketImpl),
|
|
REG_JNI(register_android_net_NetworkUtils),
|
|
REG_JNI(register_android_net_wifi_WifiManager),
|
|
REG_JNI(register_android_os_MemoryFile),
|
|
REG_JNI(register_com_android_internal_os_ZygoteInit),
|
|
REG_JNI(register_android_hardware_Camera),
|
|
REG_JNI(register_android_hardware_SensorManager),
|
|
REG_JNI(register_android_media_AudioRecord),
|
|
REG_JNI(register_android_media_AudioSystem),
|
|
REG_JNI(register_android_media_AudioTrack),
|
|
REG_JNI(register_android_media_JetPlayer),
|
|
REG_JNI(register_android_media_ToneGenerator),
|
|
|
|
REG_JNI(register_android_opengl_classes),
|
|
REG_JNI(register_android_bluetooth_Database),
|
|
REG_JNI(register_android_bluetooth_HeadsetBase),
|
|
REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
|
|
REG_JNI(register_android_bluetooth_RfcommSocket),
|
|
REG_JNI(register_android_bluetooth_ScoSocket),
|
|
REG_JNI(register_android_server_BluetoothDeviceService),
|
|
REG_JNI(register_android_server_BluetoothEventLoop),
|
|
REG_JNI(register_android_server_BluetoothA2dpService),
|
|
REG_JNI(register_android_message_digest_sha1),
|
|
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
|
|
REG_JNI(register_android_util_Base64),
|
|
REG_JNI(register_android_location_GpsLocationProvider),
|
|
};
|
|
|
|
/*
|
|
* Register android native functions with the VM.
|
|
*/
|
|
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
|
|
{
|
|
/*
|
|
* This hook causes all future threads created in this process to be
|
|
* attached to the JavaVM. (This needs to go away in favor of JNI
|
|
* Attach calls.)
|
|
*/
|
|
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
|
|
|
|
LOGD("--- registering native functions ---\n");
|
|
|
|
/*
|
|
* Every "register" function calls one or more things that return
|
|
* a local reference (e.g. FindClass). Because we haven't really
|
|
* started the VM yet, they're all getting stored in the base frame
|
|
* and never released. Use Push/Pop to manage the storage.
|
|
*/
|
|
env->PushLocalFrame(200);
|
|
|
|
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
|
|
env->PopLocalFrame(NULL);
|
|
return -1;
|
|
}
|
|
env->PopLocalFrame(NULL);
|
|
|
|
//createJavaThread("fubar", quickTest, (void*) "hello");
|
|
|
|
return 0;
|
|
}
|
|
|
|
AndroidRuntime* AndroidRuntime::getRuntime()
|
|
{
|
|
return gCurRuntime;
|
|
}
|
|
|
|
/**
|
|
* Used by WithFramework to register native functions.
|
|
*/
|
|
extern "C"
|
|
jint Java_com_android_internal_util_WithFramework_registerNatives(
|
|
JNIEnv* env, jclass clazz) {
|
|
return register_jni_procs(gRegJNI, NELEM(gRegJNI), env);
|
|
}
|
|
|
|
/**
|
|
* Used by LoadClass to register native functions.
|
|
*/
|
|
extern "C"
|
|
jint Java_LoadClass_registerNatives(JNIEnv* env, jclass clazz) {
|
|
return register_jni_procs(gRegJNI, NELEM(gRegJNI), env);
|
|
}
|
|
|
|
} // namespace android
|