Home | History | Annotate | Download | only in app_process
      1 /*
      2  * Main entry of app process.
      3  *
      4  * Starts the interpreted runtime, then starts up the application.
      5  *
      6  */
      7 
      8 #define LOG_TAG "appproc"
      9 
     10 #include <cutils/properties.h>
     11 #include <binder/IPCThreadState.h>
     12 #include <binder/ProcessState.h>
     13 #include <utils/Log.h>
     14 #include <cutils/process_name.h>
     15 #include <cutils/memory.h>
     16 #include <cutils/trace.h>
     17 #include <android_runtime/AndroidRuntime.h>
     18 #include <sys/personality.h>
     19 
     20 #include <stdlib.h>
     21 #include <stdio.h>
     22 #include <unistd.h>
     23 
     24 namespace android {
     25 
     26 void app_usage()
     27 {
     28     fprintf(stderr,
     29         "Usage: app_process [java-options] cmd-dir start-class-name [options]\n");
     30 }
     31 
     32 class AppRuntime : public AndroidRuntime
     33 {
     34 public:
     35     AppRuntime()
     36         : mParentDir(NULL)
     37         , mClassName(NULL)
     38         , mClass(NULL)
     39         , mArgC(0)
     40         , mArgV(NULL)
     41     {
     42     }
     43 
     44 #if 0
     45     // this appears to be unused
     46     const char* getParentDir() const
     47     {
     48         return mParentDir;
     49     }
     50 #endif
     51 
     52     const char* getClassName() const
     53     {
     54         return mClassName;
     55     }
     56 
     57     virtual void onVmCreated(JNIEnv* env)
     58     {
     59         if (mClassName == NULL) {
     60             return; // Zygote. Nothing to do here.
     61         }
     62 
     63         /*
     64          * This is a little awkward because the JNI FindClass call uses the
     65          * class loader associated with the native method we're executing in.
     66          * If called in onStarted (from RuntimeInit.finishInit because we're
     67          * launching "am", for example), FindClass would see that we're calling
     68          * from a boot class' native method, and so wouldn't look for the class
     69          * we're trying to look up in CLASSPATH. Unfortunately it needs to,
     70          * because the "am" classes are not boot classes.
     71          *
     72          * The easiest fix is to call FindClass here, early on before we start
     73          * executing boot class Java code and thereby deny ourselves access to
     74          * non-boot classes.
     75          */
     76         char* slashClassName = toSlashClassName(mClassName);
     77         mClass = env->FindClass(slashClassName);
     78         if (mClass == NULL) {
     79             ALOGE("ERROR: could not find class '%s'\n", mClassName);
     80         }
     81         free(slashClassName);
     82 
     83         mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
     84     }
     85 
     86     virtual void onStarted()
     87     {
     88         sp<ProcessState> proc = ProcessState::self();
     89         ALOGV("App process: starting thread pool.\n");
     90         proc->startThreadPool();
     91 
     92         AndroidRuntime* ar = AndroidRuntime::getRuntime();
     93         ar->callMain(mClassName, mClass, mArgC, mArgV);
     94 
     95         IPCThreadState::self()->stopProcess();
     96     }
     97 
     98     virtual void onZygoteInit()
     99     {
    100         // Re-enable tracing now that we're no longer in Zygote.
    101         atrace_set_tracing_enabled(true);
    102 
    103         sp<ProcessState> proc = ProcessState::self();
    104         ALOGV("App process: starting thread pool.\n");
    105         proc->startThreadPool();
    106     }
    107 
    108     virtual void onExit(int code)
    109     {
    110         if (mClassName == NULL) {
    111             // if zygote
    112             IPCThreadState::self()->stopProcess();
    113         }
    114 
    115         AndroidRuntime::onExit(code);
    116     }
    117 
    118 
    119     const char* mParentDir;
    120     const char* mClassName;
    121     jclass mClass;
    122     int mArgC;
    123     const char* const* mArgV;
    124 };
    125 
    126 }
    127 
    128 using namespace android;
    129 
    130 /*
    131  * sets argv0 to as much of newArgv0 as will fit
    132  */
    133 static void setArgv0(const char *argv0, const char *newArgv0)
    134 {
    135     strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
    136 }
    137 
    138 int main(int argc, char* const argv[])
    139 {
    140 #ifdef __arm__
    141     /*
    142      * b/7188322 - Temporarily revert to the compat memory layout
    143      * to avoid breaking third party apps.
    144      *
    145      * THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.
    146      *
    147      * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466
    148      * changes the kernel mapping from bottom up to top-down.
    149      * This breaks some programs which improperly embed
    150      * an out of date copy of Android's linker.
    151      */
    152     char value[PROPERTY_VALUE_MAX];
    153     property_get("ro.kernel.qemu", value, "");
    154     bool is_qemu = (strcmp(value, "1") == 0);
    155     if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && !is_qemu) {
    156         int current = personality(0xFFFFFFFF);
    157         if ((current & ADDR_COMPAT_LAYOUT) == 0) {
    158             personality(current | ADDR_COMPAT_LAYOUT);
    159             setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);
    160             execv("/system/bin/app_process", argv);
    161             return -1;
    162         }
    163     }
    164     unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");
    165 #endif
    166 
    167     // These are global variables in ProcessState.cpp
    168     mArgC = argc;
    169     mArgV = argv;
    170 
    171     mArgLen = 0;
    172     for (int i=0; i<argc; i++) {
    173         mArgLen += strlen(argv[i]) + 1;
    174     }
    175     mArgLen--;
    176 
    177     AppRuntime runtime;
    178     const char* argv0 = argv[0];
    179 
    180     // Process command line arguments
    181     // ignore argv[0]
    182     argc--;
    183     argv++;
    184 
    185     // Everything up to '--' or first non '-' arg goes to the vm
    186 
    187     int i = runtime.addVmArguments(argc, argv);
    188 
    189     // Parse runtime arguments.  Stop at first unrecognized option.
    190     bool zygote = false;
    191     bool startSystemServer = false;
    192     bool application = false;
    193     const char* parentDir = NULL;
    194     const char* niceName = NULL;
    195     const char* className = NULL;
    196     while (i < argc) {
    197         const char* arg = argv[i++];
    198         if (!parentDir) {
    199             parentDir = arg;
    200         } else if (strcmp(arg, "--zygote") == 0) {
    201             zygote = true;
    202             niceName = "zygote";
    203         } else if (strcmp(arg, "--start-system-server") == 0) {
    204             startSystemServer = true;
    205         } else if (strcmp(arg, "--application") == 0) {
    206             application = true;
    207         } else if (strncmp(arg, "--nice-name=", 12) == 0) {
    208             niceName = arg + 12;
    209         } else {
    210             className = arg;
    211             break;
    212         }
    213     }
    214 
    215     if (niceName && *niceName) {
    216         setArgv0(argv0, niceName);
    217         set_process_name(niceName);
    218     }
    219 
    220     runtime.mParentDir = parentDir;
    221 
    222     if (zygote) {
    223         runtime.start("com.android.internal.os.ZygoteInit",
    224                 startSystemServer ? "start-system-server" : "");
    225     } else if (className) {
    226         // Remainder of args get passed to startup class main()
    227         runtime.mClassName = className;
    228         runtime.mArgC = argc - i;
    229         runtime.mArgV = argv + i;
    230         runtime.start("com.android.internal.os.RuntimeInit",
    231                 application ? "application" : "tool");
    232     } else {
    233         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
    234         app_usage();
    235         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    236         return 10;
    237     }
    238 }
    239