blob: 40dc2a1dc4d13fb45dddb9dde719e0769bb2651e [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/* //device/libs/android_runtime/AndroidRuntime.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define LOG_TAG "AndroidRuntime"
19//#define LOG_NDEBUG 0
20
21#include <android_runtime/AndroidRuntime.h>
22#include <utils/IBinder.h>
23#include <utils/IServiceManager.h>
24#include <utils/Log.h>
25#include <utils/misc.h>
26#include <utils/Parcel.h>
27#include <utils/string_array.h>
28#include <utils/threads.h>
29#include <cutils/properties.h>
30
31#include <SkGraphics.h>
32#include <SkImageDecoder.h>
33
34#include "jni.h"
35#include "JNIHelp.h"
36#include "android_util_Binder.h"
37
38#include <stdio.h>
39#include <signal.h>
40#include <sys/stat.h>
41#include <sys/types.h>
42#include <signal.h>
43#include <dirent.h>
44#include <assert.h>
45
46
47using namespace android;
48
49extern void register_BindTest();
50
51extern int register_android_os_Binder(JNIEnv* env);
52extern int register_android_os_Process(JNIEnv* env);
53extern int register_android_graphics_Bitmap(JNIEnv*);
54extern int register_android_graphics_BitmapFactory(JNIEnv*);
55extern int register_android_graphics_Camera(JNIEnv* env);
56extern int register_android_graphics_Graphics(JNIEnv* env);
57extern int register_android_graphics_Interpolator(JNIEnv* env);
58extern int register_android_graphics_LayerRasterizer(JNIEnv*);
59extern int register_android_graphics_MaskFilter(JNIEnv* env);
60extern int register_android_graphics_Movie(JNIEnv* env);
61extern int register_android_graphics_NinePatch(JNIEnv*);
62extern int register_android_graphics_PathEffect(JNIEnv* env);
63extern int register_android_graphics_Region(JNIEnv* env);
64extern int register_android_graphics_Shader(JNIEnv* env);
65extern int register_android_graphics_Typeface(JNIEnv* env);
66
67extern int register_com_google_android_gles_jni_EGLImpl(JNIEnv* env);
68extern int register_com_google_android_gles_jni_GLImpl(JNIEnv* env);
69
70extern int register_android_hardware_Camera(JNIEnv *env);
71
72extern int register_android_hardware_SensorManager(JNIEnv *env);
73
74extern int register_android_media_AudioRecord(JNIEnv *env);
75extern int register_android_media_AudioSystem(JNIEnv *env);
76extern int register_android_media_AudioTrack(JNIEnv *env);
77extern int register_android_media_JetPlayer(JNIEnv *env);
78extern int register_android_media_ToneGenerator(JNIEnv *env);
79
80extern int register_android_message_digest_sha1(JNIEnv *env);
81
82extern int register_android_util_FloatMath(JNIEnv* env);
83
84namespace android {
85
86/*
87 * JNI-based registration functions. Note these are properly contained in
88 * namespace android.
89 */
90extern int register_android_content_AssetManager(JNIEnv* env);
91extern int register_android_util_EventLog(JNIEnv* env);
92extern int register_android_util_Log(JNIEnv* env);
93extern int register_android_content_StringBlock(JNIEnv* env);
94extern int register_android_content_XmlBlock(JNIEnv* env);
95extern int register_android_graphics_Canvas(JNIEnv* env);
96extern int register_android_graphics_ColorFilter(JNIEnv* env);
97extern int register_android_graphics_DrawFilter(JNIEnv* env);
98extern int register_android_graphics_Matrix(JNIEnv* env);
99extern int register_android_graphics_Paint(JNIEnv* env);
100extern int register_android_graphics_Path(JNIEnv* env);
101extern int register_android_graphics_PathMeasure(JNIEnv* env);
102extern int register_android_graphics_Picture(JNIEnv*);
103extern int register_android_graphics_PorterDuff(JNIEnv* env);
104extern int register_android_graphics_Rasterizer(JNIEnv* env);
105extern int register_android_graphics_Xfermode(JNIEnv* env);
106extern int register_android_graphics_PixelFormat(JNIEnv* env);
107extern int register_com_android_internal_graphics_NativeUtils(JNIEnv *env);
108extern int register_android_view_Display(JNIEnv* env);
109extern int register_android_view_Surface(JNIEnv* env);
110extern int register_android_view_ViewRoot(JNIEnv* env);
111extern int register_android_database_CursorWindow(JNIEnv* env);
112extern int register_android_database_SQLiteDatabase(JNIEnv* env);
113extern int register_android_database_SQLiteDebug(JNIEnv* env);
114extern int register_android_database_SQLiteProgram(JNIEnv* env);
115extern int register_android_database_SQLiteQuery(JNIEnv* env);
116extern int register_android_database_SQLiteStatement(JNIEnv* env);
117extern int register_android_debug_JNITest(JNIEnv* env);
118extern int register_android_nio_utils(JNIEnv* env);
119extern int register_android_pim_EventRecurrence(JNIEnv* env);
120extern int register_android_text_format_Time(JNIEnv* env);
121extern int register_android_os_Debug(JNIEnv* env);
122extern int register_android_os_ParcelFileDescriptor(JNIEnv *env);
123extern int register_android_os_Power(JNIEnv *env);
124extern int register_android_os_StatFs(JNIEnv *env);
125extern int register_android_os_SystemProperties(JNIEnv *env);
126extern int register_android_os_Hardware(JNIEnv* env);
127extern int register_android_os_Exec(JNIEnv *env);
128extern int register_android_os_SystemClock(JNIEnv* env);
129extern int register_android_os_FileObserver(JNIEnv *env);
130extern int register_android_os_FileUtils(JNIEnv *env);
131extern int register_android_os_UEventObserver(JNIEnv* env);
132extern int register_android_os_MemoryFile(JNIEnv* env);
133extern int register_android_net_LocalSocketImpl(JNIEnv* env);
134extern int register_android_net_NetworkUtils(JNIEnv* env);
135extern int register_android_net_wifi_WifiManager(JNIEnv* env);
136extern int register_android_security_Md5MessageDigest(JNIEnv *env);
137extern int register_android_text_AndroidCharacter(JNIEnv *env);
138extern int register_android_text_KeyCharacterMap(JNIEnv *env);
139extern int register_android_opengl_classes(JNIEnv *env);
140extern int register_android_bluetooth_Database(JNIEnv* env);
141extern int register_android_bluetooth_HeadsetBase(JNIEnv* env);
142extern int register_android_bluetooth_BluetoothAudioGateway(JNIEnv* env);
143extern int register_android_bluetooth_RfcommSocket(JNIEnv *env);
144extern int register_android_bluetooth_ScoSocket(JNIEnv *env);
145extern int register_android_server_BluetoothDeviceService(JNIEnv* env);
146extern int register_android_server_BluetoothEventLoop(JNIEnv *env);
147extern int register_android_server_BluetoothA2dpService(JNIEnv* env);
148extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
149extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env);
150extern int register_android_util_Base64(JNIEnv* env);
151extern int register_android_location_GpsLocationProvider(JNIEnv* env);
152
153static AndroidRuntime* gCurRuntime = NULL;
154
155static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
156{
157 if (jniThrowException(env, exc, msg) != 0)
158 assert(false);
159}
160
161/*
162 * Code written in the Java Programming Language calls here from main().
163 */
164static void com_android_internal_os_RuntimeInit_finishInit(JNIEnv* env, jobject clazz)
165{
166 gCurRuntime->onStarted();
167}
168
169static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)
170{
171 gCurRuntime->onZygoteInit();
172}
173
174static jint com_android_internal_os_RuntimeInit_isComputerOn(JNIEnv* env, jobject clazz)
175{
176 return 1;
177}
178
179static void com_android_internal_os_RuntimeInit_turnComputerOn(JNIEnv* env, jobject clazz)
180{
181}
182
183static jint com_android_internal_os_RuntimeInit_getQwertyKeyboard(JNIEnv* env, jobject clazz)
184{
185 char* value = getenv("qwerty");
186 if (value != NULL && strcmp(value, "true") == 0) {
187 return 1;
188 }
189
190 return 0;
191}
192
193/*
194 * JNI registration.
195 */
196static JNINativeMethod gMethods[] = {
197 { "finishInit", "()V",
198 (void*) com_android_internal_os_RuntimeInit_finishInit },
199 { "zygoteInitNative", "()V",
200 (void*) com_android_internal_os_RuntimeInit_zygoteInit },
201 { "isComputerOn", "()I",
202 (void*) com_android_internal_os_RuntimeInit_isComputerOn },
203 { "turnComputerOn", "()V",
204 (void*) com_android_internal_os_RuntimeInit_turnComputerOn },
205 { "getQwertyKeyboard", "()I",
206 (void*) com_android_internal_os_RuntimeInit_getQwertyKeyboard },
207};
208
209int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
210{
211 return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit",
212 gMethods, NELEM(gMethods));
213}
214
215// ----------------------------------------------------------------------
216
217/*static*/ JavaVM* AndroidRuntime::mJavaVM = NULL;
218
219
220AndroidRuntime::AndroidRuntime()
221{
222 SkGraphics::Init(false); // true means run unittests (slow)
223 // this sets our preference for 16bit images during decode
224 // in case the src is opaque and 24bit
225 SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
226
227 // Pre-allocate enough space to hold a fair number of options.
228 mOptions.setCapacity(20);
229
230 assert(gCurRuntime == NULL); // one per process
231 gCurRuntime = this;
232}
233
234AndroidRuntime::~AndroidRuntime()
235{
236 SkGraphics::Term();
237}
238
239/*
240 * Register native methods using JNI.
241 */
242/*static*/ int AndroidRuntime::registerNativeMethods(JNIEnv* env,
243 const char* className, const JNINativeMethod* gMethods, int numMethods)
244{
245 return jniRegisterNativeMethods(env, className, gMethods, numMethods);
246}
247
248/*
249 * Call a static Java Programming Language function that takes no arguments and returns void.
250 */
251status_t AndroidRuntime::callStatic(const char* className, const char* methodName)
252{
253 JNIEnv* env;
254 jclass clazz;
255 jmethodID methodId;
256
257 env = getJNIEnv();
258 if (env == NULL)
259 return UNKNOWN_ERROR;
260
261 clazz = findClass(env, className);
262 if (clazz == NULL) {
263 LOGE("ERROR: could not find class '%s'\n", className);
264 return UNKNOWN_ERROR;
265 }
266 methodId = env->GetStaticMethodID(clazz, methodName, "()V");
267 if (methodId == NULL) {
268 LOGE("ERROR: could not find method %s.%s\n", className, methodName);
269 return UNKNOWN_ERROR;
270 }
271
272 env->CallStaticVoidMethod(clazz, methodId);
273
274 return NO_ERROR;
275}
276
277status_t AndroidRuntime::callMain(
278 const char* className, int argc, const char* const argv[])
279{
280 JNIEnv* env;
281 jclass clazz;
282 jmethodID methodId;
283
284 env = getJNIEnv();
285 if (env == NULL)
286 return UNKNOWN_ERROR;
287
288 clazz = findClass(env, className);
289 if (clazz == NULL) {
290 LOGE("ERROR: could not find class '%s'\n", className);
291 return UNKNOWN_ERROR;
292 }
293
294 methodId = env->GetStaticMethodID(clazz, "main", "([Ljava/lang/String;)V");
295 if (methodId == NULL) {
296 LOGE("ERROR: could not find method %s.main(String[])\n", className);
297 return UNKNOWN_ERROR;
298 }
299
300 /*
301 * We want to call main() with a String array with our arguments in it.
302 * Create an array and populate it.
303 */
304 jclass stringClass;
305 jobjectArray strArray;
306
307 stringClass = env->FindClass("java/lang/String");
308 strArray = env->NewObjectArray(argc, stringClass, NULL);
309
310 for (int i = 0; i < argc; i++) {
311 jstring argStr = env->NewStringUTF(argv[i]);
312 env->SetObjectArrayElement(strArray, i, argStr);
313 }
314
315 env->CallStaticVoidMethod(clazz, methodId, strArray);
316 return NO_ERROR;
317}
318
319/*
320 * Find the named class.
321 */
322jclass AndroidRuntime::findClass(JNIEnv* env, const char* className)
323{
324 char* convName = NULL;
325
326 if (env->ExceptionCheck()) {
327 LOGE("ERROR: exception pending on entry to findClass()\n");
328 return NULL;
329 }
330
331 /*
332 * JNI FindClass uses class names with slashes, but ClassLoader.loadClass
333 * uses the dotted "binary name" format. We don't need to convert the
334 * name with the new approach.
335 */
336#if 0
337 /* (convName only created if necessary -- use className) */
338 for (char* cp = const_cast<char*>(className); *cp != '\0'; cp++) {
339 if (*cp == '.') {
340 if (convName == NULL) {
341 convName = strdup(className);
342 cp = convName + (cp-className);
343 className = convName;
344 }
345 *cp = '/';
346 }
347 }
348#endif
349
350 /*
351 * This is a little awkward because the JNI FindClass call uses the
352 * class loader associated with the native method we're executing in.
353 * Because this native method is part of a "boot" class, JNI doesn't
354 * look for the class in CLASSPATH, which unfortunately is a likely
355 * location for it. (Had we issued the FindClass call before calling
356 * into the VM -- at which point there isn't a native method frame on
357 * the stack -- the VM would have checked CLASSPATH. We have to do
358 * this because we call into Java Programming Language code and
359 * bounce back out.)
360 *
361 * JNI lacks a "find class in a specific class loader" operation, so we
362 * have to do things the hard way.
363 */
364 jclass cls = NULL;
365 //cls = env->FindClass(className);
366
367 jclass javaLangClassLoader;
368 jmethodID getSystemClassLoader, loadClass;
369 jobject systemClassLoader;
370 jstring strClassName;
371
372 /* find the "system" class loader; none of this is expected to fail */
373 javaLangClassLoader = env->FindClass("java/lang/ClassLoader");
374 assert(javaLangClassLoader != NULL);
375 getSystemClassLoader = env->GetStaticMethodID(javaLangClassLoader,
376 "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
377 loadClass = env->GetMethodID(javaLangClassLoader,
378 "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
379 assert(getSystemClassLoader != NULL && loadClass != NULL);
380 systemClassLoader = env->CallStaticObjectMethod(javaLangClassLoader,
381 getSystemClassLoader);
382 assert(systemClassLoader != NULL);
383
384 /* create an object for the class name string; alloc could fail */
385 strClassName = env->NewStringUTF(className);
386 if (env->ExceptionCheck()) {
387 LOGE("ERROR: unable to convert '%s' to string\n", className);
388 goto bail;
389 }
390 LOGV("system class loader is %p, loading %p (%s)\n",
391 systemClassLoader, strClassName, className);
392
393 /* try to find the named class */
394 cls = (jclass) env->CallObjectMethod(systemClassLoader, loadClass,
395 strClassName);
396 if (env->ExceptionCheck()) {
397 LOGE("ERROR: unable to load class '%s' from %p\n",
398 className, systemClassLoader);
399 cls = NULL;
400 goto bail;
401 }
402
403bail:
404 free(convName);
405 return cls;
406}
407
408/*
409 * The VM calls this through the "exit" hook.
410 */
411static void runtime_exit(int code)
412{
413 gCurRuntime->onExit(code);
414 exit(code);
415}
416
417/*
418 * The VM calls this through the "vfprintf" hook.
419 *
420 * We ignore "fp" and just write the results to the log file.
421 */
422static void runtime_vfprintf(FILE* fp, const char* format, va_list ap)
423{
424 LOG_PRI_VA(ANDROID_LOG_INFO, "vm-printf", format, ap);
425}
426
427
428/**
429 * Add VM arguments to the to-be-executed VM
430 * Stops at first non '-' argument (also stops at an argument of '--')
431 * Returns the number of args consumed
432 */
433int AndroidRuntime::addVmArguments(int argc, const char* const argv[])
434{
435 int i;
436
437 for (i = 0; i<argc; i++) {
438 if (argv[i][0] != '-') {
439 return i;
440 }
441 if (argv[i][1] == '-' && argv[i][2] == 0) {
442 return i+1;
443 }
444
445 JavaVMOption opt;
446 memset(&opt, 0, sizeof(opt));
447 opt.optionString = (char*)argv[i];
448 mOptions.add(opt);
449 }
450 return i;
451}
452
453static int hasDir(const char* dir)
454{
455 struct stat s;
456 int res = stat(dir, &s);
457 if (res == 0) {
458 return S_ISDIR(s.st_mode);
459 }
460 return 0;
461}
462
463/*
464 * We just want failed write() calls to just return with an error.
465 */
466static void blockSigpipe()
467{
468 sigset_t mask;
469
470 sigemptyset(&mask);
471 sigaddset(&mask, SIGPIPE);
472 if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
473 LOGW("WARNING: SIGPIPE not blocked\n");
474}
475
476/*
477 * Read the persistent locale.
478 */
479static void readLocale(char* language, char* region)
480{
481 char propLang[PROPERTY_VALUE_MAX], propRegn[PROPERTY_VALUE_MAX];
482
483 property_get("persist.sys.language", propLang, "");
484 property_get("persist.sys.country", propRegn, "");
485 if (*propLang == 0 && *propRegn == 0) {
486 /* Set to ro properties, default is en_US */
487 property_get("ro.product.locale.language", propLang, "en");
488 property_get("ro.product.locale.region", propRegn, "US");
489 }
490 strncat(language, propLang, 2);
491 strncat(region, propRegn, 2);
492 //LOGD("language=%s region=%s\n", language, region);
493}
494
495void AndroidRuntime::start(const char* className, const bool startSystemServer)
496{
497 LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");
498
499 JNIEnv* env;
500 JavaVMInitArgs initArgs;
501 JavaVMOption opt;
502 char propBuf[PROPERTY_VALUE_MAX];
503 char stackTraceFileBuf[PROPERTY_VALUE_MAX];
504 char dexoptFlagsBuf[PROPERTY_VALUE_MAX];
505 char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];
506 char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
507 char* stackTraceFile = NULL;
508 char* slashClassName = NULL;
509 char* cp;
510 bool checkJni = false;
511 bool logStdio = false;
512 enum { kEMDefault, kEMIntPortable, kEMIntFast } executionMode = kEMDefault;
513
514 blockSigpipe();
515
516 /*
517 * 'startSystemServer == true' means runtime is obslete and not run from
518 * init.rc anymore, so we print out the boot start event here.
519 */
520 if (startSystemServer) {
521 /* track our progress through the boot sequence */
522 const int LOG_BOOT_PROGRESS_START = 3000;
523 LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
524 ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
525 }
526
527 property_get("dalvik.vm.checkjni", propBuf, "");
528 if (strcmp(propBuf, "true") == 0) {
529 checkJni = true;
530 } else if (strcmp(propBuf, "false") != 0) {
531 /* property is neither true nor false; fall back on kernel parameter */
532 property_get("ro.kernel.android.checkjni", propBuf, "");
533 if (propBuf[0] == '1') {
534 checkJni = true;
535 }
536 }
537
538 property_get("dalvik.vm.execution-mode", propBuf, "");
539 if (strcmp(propBuf, "int:portable") == 0) {
540 executionMode = kEMIntPortable;
541 } else if (strcmp(propBuf, "int:fast") == 0) {
542 executionMode = kEMIntFast;
543 }
544
545 property_get("dalvik.vm.stack-trace-file", stackTraceFileBuf, "");
546
547 property_get("log.redirect-stdio", propBuf, "");
548 if (strcmp(propBuf, "true") == 0) {
549 logStdio = true;
550 }
551
552 strcpy(enableAssertBuf, "-ea:");
553 property_get("dalvik.vm.enableassertions", enableAssertBuf+4, "");
554
555 strcpy(jniOptsBuf, "-Xjniopts:");
556 property_get("dalvik.vm.jniopts", jniOptsBuf+10, "");
557
558 const char* rootDir = getenv("ANDROID_ROOT");
559 if (rootDir == NULL) {
560 rootDir = "/system";
561 if (!hasDir("/system")) {
562 LOG_FATAL("No root directory specified, and /android does not exist.");
563 return;
564 }
565 setenv("ANDROID_ROOT", rootDir, 1);
566 }
567
568 const char* kernelHack = getenv("LD_ASSUME_KERNEL");
569 //LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
570
571 /* route exit() to our handler */
572 opt.extraInfo = (void*) runtime_exit;
573 opt.optionString = "exit";
574 mOptions.add(opt);
575
576 /* route fprintf() to our handler */
577 opt.extraInfo = (void*) runtime_vfprintf;
578 opt.optionString = "vfprintf";
579 mOptions.add(opt);
580
581 opt.extraInfo = NULL;
582
583 /* enable verbose; standard options are { jni, gc, class } */
584 //options[curOpt++].optionString = "-verbose:jni";
585 opt.optionString = "-verbose:gc";
586 mOptions.add(opt);
587 //options[curOpt++].optionString = "-verbose:class";
588
589#ifdef CUSTOM_RUNTIME_HEAP_MAX
590#define __make_max_heap_opt(val) #val
591#define _make_max_heap_opt(val) "-Xmx" __make_max_heap_opt(val)
592 opt.optionString = _make_max_heap_opt(CUSTOM_RUNTIME_HEAP_MAX);
593#undef __make_max_heap_opt
594#undef _make_max_heap_opt
595#else
596 /* limit memory use to 16MB */
597 opt.optionString = "-Xmx16m";
598#endif
599 mOptions.add(opt);
600
601 /*
602 * Enable or disable dexopt features, such as bytecode verification and
603 * calculation of register maps for precise GC.
604 */
605 property_get("dalvik.vm.dexopt-flags", dexoptFlagsBuf, "");
606 if (dexoptFlagsBuf[0] != '\0') {
607 const char* opc;
608 const char* val;
609
610 opc = strstr(dexoptFlagsBuf, "v="); /* verification */
611 if (opc != NULL) {
612 switch (*(opc+2)) {
613 case 'n': val = "-Xverify:none"; break;
614 case 'r': val = "-Xverify:remote"; break;
615 case 'a': val = "-Xverify:all"; break;
616 default: val = NULL; break;
617 }
618
619 if (val != NULL) {
620 opt.optionString = val;
621 mOptions.add(opt);
622 }
623 }
624
625 opc = strstr(dexoptFlagsBuf, "o="); /* optimization */
626 if (opc != NULL) {
627 switch (*(opc+2)) {
628 case 'n': val = "-Xdexopt:none"; break;
629 case 'v': val = "-Xdexopt:verified"; break;
630 case 'a': val = "-Xdexopt:all"; break;
631 default: val = NULL; break;
632 }
633
634 if (val != NULL) {
635 opt.optionString = val;
636 mOptions.add(opt);
637 }
638 }
639
640 opc = strstr(dexoptFlagsBuf, "m=y"); /* register map */
641 if (opc != NULL) {
642 opt.optionString = "-Xgenregmap";
643 mOptions.add(opt);
644 }
645 }
646
647 /* enable debugging; set suspend=y to pause during VM init */
648#ifdef HAVE_ANDROID_OS
649 /* use android ADB transport */
650 opt.optionString =
651 "-agentlib:jdwp=transport=dt_android_adb,suspend=n,server=y";
652#else
653 /* use TCP socket; address=0 means start at port 8000 and probe up */
654 LOGI("Using TCP socket for JDWP\n");
655 opt.optionString =
656 "-agentlib:jdwp=transport=dt_socket,suspend=n,server=y,address=0";
657#endif
658 mOptions.add(opt);
659
660 char enableDPBuf[sizeof("-Xdeadlockpredict:") + PROPERTY_VALUE_MAX];
661 property_get("dalvik.vm.deadlock-predict", propBuf, "");
662 if (strlen(propBuf) > 0) {
663 strcpy(enableDPBuf, "-Xdeadlockpredict:");
664 strcat(enableDPBuf, propBuf);
665 opt.optionString = enableDPBuf;
666 mOptions.add(opt);
667 }
668
669 LOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
670 if (checkJni) {
671 /* extended JNI checking */
672 opt.optionString = "-Xcheck:jni";
673 mOptions.add(opt);
674
675 /* set a cap on JNI global references */
676 opt.optionString = "-Xjnigreflimit:2000";
677 mOptions.add(opt);
678
679 /* with -Xcheck:jni, this provides a JNI function call trace */
680 //opt.optionString = "-verbose:jni";
681 //mOptions.add(opt);
682 }
683 if (executionMode == kEMIntPortable) {
684 opt.optionString = "-Xint:portable";
685 mOptions.add(opt);
686 } else if (executionMode == kEMIntFast) {
687 opt.optionString = "-Xint:fast";
688 mOptions.add(opt);
689 }
690 if (logStdio) {
691 /* convert stdout/stderr to log messages */
692 opt.optionString = "-Xlog-stdio";
693 mOptions.add(opt);
694 }
695
696 if (enableAssertBuf[4] != '\0') {
697 /* accept "all" to mean "all classes and packages" */
698 if (strcmp(enableAssertBuf+4, "all") == 0)
699 enableAssertBuf[3] = '\0';
700 LOGI("Assertions enabled: '%s'\n", enableAssertBuf);
701 opt.optionString = enableAssertBuf;
702 mOptions.add(opt);
703 } else {
704 LOGV("Assertions disabled\n");
705 }
706
707 if (jniOptsBuf[10] != '\0') {
708 LOGI("JNI options: '%s'\n", jniOptsBuf);
709 opt.optionString = jniOptsBuf;
710 mOptions.add(opt);
711 }
712
713 if (stackTraceFileBuf[0] != '\0') {
714 static const char* stfOptName = "-Xstacktracefile:";
715
716 stackTraceFile = (char*) malloc(strlen(stfOptName) +
717 strlen(stackTraceFileBuf) +1);
718 strcpy(stackTraceFile, stfOptName);
719 strcat(stackTraceFile, stackTraceFileBuf);
720 opt.optionString = stackTraceFile;
721 mOptions.add(opt);
722 }
723
724 /* Set the properties for locale */
725 {
726 char langOption[sizeof("-Duser.language=") + 3];
727 char regionOption[sizeof("-Duser.region=") + 3];
728 strcpy(langOption, "-Duser.language=");
729 strcpy(regionOption, "-Duser.region=");
730 readLocale(langOption, regionOption);
731 opt.extraInfo = NULL;
732 opt.optionString = langOption;
733 mOptions.add(opt);
734 opt.optionString = regionOption;
735 mOptions.add(opt);
736 }
737
738 /*
739 * We don't have /tmp on the device, but we often have an SD card. Apps
740 * shouldn't use this, but some test suites might want to exercise it.
741 */
742 opt.optionString = "-Djava.io.tmpdir=/sdcard";
743 mOptions.add(opt);
744
745 initArgs.version = JNI_VERSION_1_4;
746 initArgs.options = mOptions.editArray();
747 initArgs.nOptions = mOptions.size();
748 initArgs.ignoreUnrecognized = JNI_FALSE;
749
750 /*
751 * Initialize the VM.
752 *
753 * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
754 * If this call succeeds, the VM is ready, and we can start issuing
755 * JNI calls.
756 */
757 if (JNI_CreateJavaVM(&mJavaVM, &env, &initArgs) < 0) {
758 LOGE("JNI_CreateJavaVM failed\n");
759 goto bail;
760 }
761
762 /*
763 * Register android functions.
764 */
765 if (startReg(env) < 0) {
766 LOGE("Unable to register all android natives\n");
767 goto bail;
768 }
769
770 /*
771 * We want to call main() with a String array with arguments in it.
772 * At present we only have one argument, the class name. Create an
773 * array to hold it.
774 */
775 jclass stringClass;
776 jobjectArray strArray;
777 jstring classNameStr;
778 jstring startSystemServerStr;
779
780 stringClass = env->FindClass("java/lang/String");
781 assert(stringClass != NULL);
782 strArray = env->NewObjectArray(2, stringClass, NULL);
783 assert(strArray != NULL);
784 classNameStr = env->NewStringUTF(className);
785 assert(classNameStr != NULL);
786 env->SetObjectArrayElement(strArray, 0, classNameStr);
787 startSystemServerStr = env->NewStringUTF(startSystemServer ?
788 "true" : "false");
789 env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
790
791 /*
792 * Start VM. This thread becomes the main thread of the VM, and will
793 * not return until the VM exits.
794 */
795 jclass startClass;
796 jmethodID startMeth;
797
798 slashClassName = strdup(className);
799 for (cp = slashClassName; *cp != '\0'; cp++)
800 if (*cp == '.')
801 *cp = '/';
802
803 startClass = env->FindClass(slashClassName);
804 if (startClass == NULL) {
805 LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
806 /* keep going */
807 } else {
808 startMeth = env->GetStaticMethodID(startClass, "main",
809 "([Ljava/lang/String;)V");
810 if (startMeth == NULL) {
811 LOGE("JavaVM unable to find main() in '%s'\n", className);
812 /* keep going */
813 } else {
814 env->CallStaticVoidMethod(startClass, startMeth, strArray);
815
816#if 0
817 if (env->ExceptionCheck())
818 threadExitUncaughtException(env);
819#endif
820 }
821 }
822
823 LOGD("Shutting down VM\n");
824 if (mJavaVM->DetachCurrentThread() != JNI_OK)
825 LOGW("Warning: unable to detach main thread\n");
826 if (mJavaVM->DestroyJavaVM() != 0)
827 LOGW("Warning: VM did not shut down cleanly\n");
828
829bail:
830 free(slashClassName);
831 free(stackTraceFile);
832}
833
834void AndroidRuntime::start()
835{
836 start("com.android.internal.os.RuntimeInit",
837 false /* Don't start the system server */);
838}
839
840void AndroidRuntime::onExit(int code)
841{
842 LOGI("AndroidRuntime onExit calling exit(%d)", code);
843 exit(code);
844}
845
846/*
847 * Get the JNIEnv pointer for this thread.
848 *
849 * Returns NULL if the slot wasn't allocated or populated.
850 */
851/*static*/ JNIEnv* AndroidRuntime::getJNIEnv()
852{
853 JNIEnv* env;
854 JavaVM* vm = AndroidRuntime::getJavaVM();
855 assert(vm != NULL);
856
857 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
858 return NULL;
859 return env;
860}
861
862/*
863 * Makes the current thread visible to the VM.
864 *
865 * The JNIEnv pointer returned is only valid for the current thread, and
866 * thus must be tucked into thread-local storage.
867 */
868static int javaAttachThread(const char* threadName, JNIEnv** pEnv)
869{
870 JavaVMAttachArgs args;
871 JavaVM* vm;
872 jint result;
873
874 vm = AndroidRuntime::getJavaVM();
875 assert(vm != NULL);
876
877 args.version = JNI_VERSION_1_4;
878 args.name = (char*) threadName;
879 args.group = NULL;
880
881 result = vm->AttachCurrentThread(pEnv, (void*) &args);
882 if (result != JNI_OK)
883 LOGE("ERROR: thread attach failed\n");
884
885 return result;
886}
887
888/*
889 * Detach the current thread from the set visible to the VM.
890 */
891static int javaDetachThread(void)
892{
893 JavaVM* vm;
894 jint result;
895
896 vm = AndroidRuntime::getJavaVM();
897 assert(vm != NULL);
898
899 result = vm->DetachCurrentThread();
900 if (result != JNI_OK)
901 LOGE("ERROR: thread detach failed\n");
902 return result;
903}
904
905/*
906 * When starting a native thread that will be visible from the VM, we
907 * bounce through this to get the right attach/detach action.
908 * Note that this function calls free(args)
909 */
910/*static*/ int AndroidRuntime::javaThreadShell(void* args) {
911 void* start = ((void**)args)[0];
912 void* userData = ((void **)args)[1];
913 char* name = (char*) ((void **)args)[2]; // we own this storage
914 free(args);
915 JNIEnv* env;
916 int result;
917
918 /* hook us into the VM */
919 if (javaAttachThread(name, &env) != JNI_OK)
920 return -1;
921
922 /* start the thread running */
923 result = (*(android_thread_func_t)start)(userData);
924
925 /* unhook us */
926 javaDetachThread();
927 free(name);
928
929 return result;
930}
931
932/*
933 * This is invoked from androidCreateThreadEtc() via the callback
934 * set with androidSetCreateThreadFunc().
935 *
936 * We need to create the new thread in such a way that it gets hooked
937 * into the VM before it really starts executing.
938 */
939/*static*/ int AndroidRuntime::javaCreateThreadEtc(
940 android_thread_func_t entryFunction,
941 void* userData,
942 const char* threadName,
943 int32_t threadPriority,
944 size_t threadStackSize,
945 android_thread_id_t* threadId)
946{
947 void** args = (void**) malloc(3 * sizeof(void*)); // javaThreadShell must free
948 int result;
949
950 assert(threadName != NULL);
951
952 args[0] = (void*) entryFunction;
953 args[1] = userData;
954 args[2] = (void*) strdup(threadName); // javaThreadShell must free
955
956 result = androidCreateRawThreadEtc(AndroidRuntime::javaThreadShell, args,
957 threadName, threadPriority, threadStackSize, threadId);
958 return result;
959}
960
961/*
962 * Create a thread that is visible from the VM.
963 *
964 * This is called from elsewhere in the library.
965 */
966/*static*/ void AndroidRuntime::createJavaThread(const char* name,
967 void (*start)(void *), void* arg)
968{
969 javaCreateThreadEtc((android_thread_func_t) start, arg, name,
970 ANDROID_PRIORITY_DEFAULT, 0, NULL);
971}
972
973#if 0
974static void quickTest(void* arg)
975{
976 const char* str = (const char*) arg;
977
978 printf("In quickTest: %s\n", str);
979}
980#endif
981
982#ifdef NDEBUG
983 #define REG_JNI(name) { name }
984 struct RegJNIRec {
985 int (*mProc)(JNIEnv*);
986 };
987#else
988 #define REG_JNI(name) { name, #name }
989 struct RegJNIRec {
990 int (*mProc)(JNIEnv*);
991 const char* mName;
992 };
993#endif
994
995typedef void (*RegJAMProc)();
996
997static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
998{
999 for (size_t i = 0; i < count; i++) {
1000 if (array[i].mProc(env) < 0) {
1001#ifndef NDEBUG
1002 LOGD("----------!!! %s failed to load\n", array[i].mName);
1003#endif
1004 return -1;
1005 }
1006 }
1007 return 0;
1008}
1009
1010static void register_jam_procs(const RegJAMProc array[], size_t count)
1011{
1012 for (size_t i = 0; i < count; i++) {
1013 array[i]();
1014 }
1015}
1016
1017static const RegJNIRec gRegJNI[] = {
1018 REG_JNI(register_android_debug_JNITest),
1019 REG_JNI(register_com_android_internal_os_RuntimeInit),
1020 REG_JNI(register_android_os_SystemClock),
1021 REG_JNI(register_android_util_EventLog),
1022 REG_JNI(register_android_util_Log),
1023 REG_JNI(register_android_util_FloatMath),
1024 REG_JNI(register_android_text_format_Time),
1025 REG_JNI(register_android_pim_EventRecurrence),
1026 REG_JNI(register_android_content_AssetManager),
1027 REG_JNI(register_android_content_StringBlock),
1028 REG_JNI(register_android_content_XmlBlock),
1029 REG_JNI(register_android_security_Md5MessageDigest),
1030 REG_JNI(register_android_text_AndroidCharacter),
1031 REG_JNI(register_android_text_KeyCharacterMap),
1032 REG_JNI(register_android_os_Process),
1033 REG_JNI(register_android_os_Binder),
1034 REG_JNI(register_android_os_Hardware),
1035 REG_JNI(register_android_view_Display),
1036 REG_JNI(register_android_nio_utils),
1037 REG_JNI(register_android_graphics_PixelFormat),
1038 REG_JNI(register_android_graphics_Graphics),
1039 REG_JNI(register_android_view_Surface),
1040 REG_JNI(register_android_view_ViewRoot),
1041 REG_JNI(register_com_google_android_gles_jni_EGLImpl),
1042 REG_JNI(register_com_google_android_gles_jni_GLImpl),
1043
1044 REG_JNI(register_android_graphics_Bitmap),
1045 REG_JNI(register_android_graphics_BitmapFactory),
1046 REG_JNI(register_android_graphics_Camera),
1047 REG_JNI(register_android_graphics_Canvas),
1048 REG_JNI(register_android_graphics_ColorFilter),
1049 REG_JNI(register_android_graphics_DrawFilter),
1050 REG_JNI(register_android_graphics_Interpolator),
1051 REG_JNI(register_android_graphics_LayerRasterizer),
1052 REG_JNI(register_android_graphics_MaskFilter),
1053 REG_JNI(register_android_graphics_Matrix),
1054 REG_JNI(register_android_graphics_Movie),
1055 REG_JNI(register_android_graphics_NinePatch),
1056 REG_JNI(register_android_graphics_Paint),
1057 REG_JNI(register_android_graphics_Path),
1058 REG_JNI(register_android_graphics_PathMeasure),
1059 REG_JNI(register_android_graphics_PathEffect),
1060 REG_JNI(register_android_graphics_Picture),
1061 REG_JNI(register_android_graphics_PorterDuff),
1062 REG_JNI(register_android_graphics_Rasterizer),
1063 REG_JNI(register_android_graphics_Region),
1064 REG_JNI(register_android_graphics_Shader),
1065 REG_JNI(register_android_graphics_Typeface),
1066 REG_JNI(register_android_graphics_Xfermode),
1067 REG_JNI(register_com_android_internal_graphics_NativeUtils),
1068
1069 REG_JNI(register_android_database_CursorWindow),
1070 REG_JNI(register_android_database_SQLiteDatabase),
1071 REG_JNI(register_android_database_SQLiteDebug),
1072 REG_JNI(register_android_database_SQLiteProgram),
1073 REG_JNI(register_android_database_SQLiteQuery),
1074 REG_JNI(register_android_database_SQLiteStatement),
1075 REG_JNI(register_android_os_Debug),
1076 REG_JNI(register_android_os_Exec),
1077 REG_JNI(register_android_os_FileObserver),
1078 REG_JNI(register_android_os_FileUtils),
1079 REG_JNI(register_android_os_ParcelFileDescriptor),
1080 REG_JNI(register_android_os_Power),
1081 REG_JNI(register_android_os_StatFs),
1082 REG_JNI(register_android_os_SystemProperties),
1083 REG_JNI(register_android_os_UEventObserver),
1084 REG_JNI(register_android_net_LocalSocketImpl),
1085 REG_JNI(register_android_net_NetworkUtils),
1086 REG_JNI(register_android_net_wifi_WifiManager),
1087 REG_JNI(register_android_os_MemoryFile),
1088 REG_JNI(register_com_android_internal_os_ZygoteInit),
1089 REG_JNI(register_android_hardware_Camera),
1090 REG_JNI(register_android_hardware_SensorManager),
1091 REG_JNI(register_android_media_AudioRecord),
1092 REG_JNI(register_android_media_AudioSystem),
1093 REG_JNI(register_android_media_AudioTrack),
1094 REG_JNI(register_android_media_JetPlayer),
1095 REG_JNI(register_android_media_ToneGenerator),
1096
1097 REG_JNI(register_android_opengl_classes),
1098 REG_JNI(register_android_bluetooth_Database),
1099 REG_JNI(register_android_bluetooth_HeadsetBase),
1100 REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
1101 REG_JNI(register_android_bluetooth_RfcommSocket),
1102 REG_JNI(register_android_bluetooth_ScoSocket),
1103 REG_JNI(register_android_server_BluetoothDeviceService),
1104 REG_JNI(register_android_server_BluetoothEventLoop),
1105 REG_JNI(register_android_server_BluetoothA2dpService),
1106 REG_JNI(register_android_message_digest_sha1),
1107 REG_JNI(register_android_ddm_DdmHandleNativeHeap),
1108 REG_JNI(register_android_util_Base64),
1109 REG_JNI(register_android_location_GpsLocationProvider),
1110};
1111
1112/*
1113 * Register android native functions with the VM.
1114 */
1115/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
1116{
1117 /*
1118 * This hook causes all future threads created in this process to be
1119 * attached to the JavaVM. (This needs to go away in favor of JNI
1120 * Attach calls.)
1121 */
1122 androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
1123
1124 LOGD("--- registering native functions ---\n");
1125
1126 /*
1127 * Every "register" function calls one or more things that return
1128 * a local reference (e.g. FindClass). Because we haven't really
1129 * started the VM yet, they're all getting stored in the base frame
1130 * and never released. Use Push/Pop to manage the storage.
1131 */
1132 env->PushLocalFrame(200);
1133
1134 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
1135 env->PopLocalFrame(NULL);
1136 return -1;
1137 }
1138 env->PopLocalFrame(NULL);
1139
1140 //createJavaThread("fubar", quickTest, (void*) "hello");
1141
1142 return 0;
1143}
1144
1145AndroidRuntime* AndroidRuntime::getRuntime()
1146{
1147 return gCurRuntime;
1148}
1149
1150/**
1151 * Used by WithFramework to register native functions.
1152 */
1153extern "C"
1154jint Java_com_android_internal_util_WithFramework_registerNatives(
1155 JNIEnv* env, jclass clazz) {
1156 return register_jni_procs(gRegJNI, NELEM(gRegJNI), env);
1157}
1158
1159/**
1160 * Used by LoadClass to register native functions.
1161 */
1162extern "C"
1163jint Java_LoadClass_registerNatives(JNIEnv* env, jclass clazz) {
1164 return register_jni_procs(gRegJNI, NELEM(gRegJNI), env);
1165}
1166
1167} // namespace android