165#ifdefined(__LP64__)166staticconstcharABI_LIST_PROPERTY[]="ro.product.cpu.abilist64";167staticconstcharZYGOTE_NICE_NAME[]="zygote64";168#else169staticconstcharABI_LIST_PROPERTY[]="ro.product.cpu.abilist32";170staticconstcharZYGOTE_NICE_NAME[]="zygote";171#endif172173intmain(intargc,char*constargv[])174{......256// Parse runtime arguments. Stop at first unrecognized option.257boolzygote=false;258boolstartSystemServer=false;259boolapplication=false;260String8niceName;261String8className;262263++i;// Skip unused "parent dir" argument.264while(i<argc){265constchar*arg=argv[i++];266if(strcmp(arg,"--zygote")==0){267zygote=true;268niceName=ZYGOTE_NICE_NAME;269}elseif(strcmp(arg,"--start-system-server")==0){270startSystemServer=true;271}elseif(strcmp(arg,"--application")==0){272application=true;273}elseif(strncmp(arg,"--nice-name=",12)==0){274niceName.setTo(arg+12);275}elseif(strncmp(arg,"--",2)!=0){276className.setTo(arg);277break;278}else{279--i;280break;281}282}......309if(startSystemServer){310args.add(String8("start-system-server"));311}......331if(!niceName.isEmpty()){332runtime.setArgv0(niceName.string(),true/* setProcName */);333}334335if(zygote){336runtime.start("com.android.internal.os.ZygoteInit",args,zygote);337}elseif(className){338runtime.start("com.android.internal.os.RuntimeInit",args,zygote);339}else{340fprintf(stderr,"Error: no class name or --zygote supplied.\n");341app_usage();342LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");343}344}
1112java/*
1113 * Start the Android runtime. This involves starting the virtual machine
1114 * and calling the "static void main(String[] args)" method in the class
1115 * named by "className".
1116 *
1117 * Passes the main function two arguments, the class name and the specified
1118 * options string.
1119 */1120voidAndroidRuntime::start(constchar*className,constVector<String8>&options,boolzygote)1121{......1164/* start the virtual machine */1165JniInvocationjni_invocation;1166jni_invocation.Init(NULL);1167JNIEnv*env;1168if(startVm(&mJavaVM,&env,zygote)!=0){1169return;1170}1171onVmCreated(env);11721173/*
1174 * Register android functions.
1175 */1176if(startReg(env)<0){1177ALOGE("Unable to register all android natives\n");1178return;1179}......12031204/*
1205 * Start VM. This thread becomes the main thread of the VM, and will
1206 * not return until the VM exits.
1207 */1208char*slashClassName=toSlashClassName(className!=NULL?className:"");1209jclassstartClass=env->FindClass(slashClassName);1210if(startClass==NULL){1211ALOGE("JavaVM unable to locate class '%s'\n",slashClassName);1212/* keep going */1213}else{1214jmethodIDstartMeth=env->GetStaticMethodID(startClass,"main",1215"([Ljava/lang/String;)V");1216if(startMeth==NULL){1217ALOGE("JavaVM unable to find main() in '%s'\n",className);1218/* keep going */1219}else{1220env->CallStaticVoidMethod(startClass,startMeth,strArray);1226}1227}......1235}
818@UnsupportedAppUsage819publicstaticvoidmain(Stringargv[]){820ZygoteServerzygoteServer=null;......833Runnablecaller;834try{......847booleanstartSystemServer=false;848StringzygoteSocketName="zygote";849StringabiList=null;850booleanenableLazyPreload=false;851for(inti=1;i<argv.length;i++){852if("start-system-server".equals(argv[i])){853startSystemServer=true;854}elseif("--enable-lazy-preload".equals(argv[i])){855enableLazyPreload=true;856}elseif(argv[i].startsWith(ABI_LIST_ARG)){857abiList=argv[i].substring(ABI_LIST_ARG.length());858}elseif(argv[i].startsWith(SOCKET_NAME_ARG)){859zygoteSocketName=argv[i].substring(SOCKET_NAME_ARG.length());860}else{861thrownewRuntimeException("Unknown command line argument: "+argv[i]);862}863}864865finalbooleanisPrimaryZygote=zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);866867if(abiList==null){868thrownewRuntimeException("No ABI list supplied.");869}870871// In some configurations, we avoid preloading resources and classes eagerly.872// In such cases, we will preload things prior to our first fork.873if(!enableLazyPreload){......877preload(bootTimingsTraceLog);......881}else{882Zygote.resetNicePriority();883}......896Zygote.initNativeState(isPrimaryZygote);897898ZygoteHooks.stopZygoteNoThreadCreation();899900zygoteServer=newZygoteServer(isPrimaryZygote);901902if(startSystemServer){903Runnabler=forkSystemServer(abiList,zygoteSocketName,zygoteServer);904905// {@code r == null} in the parent (zygote) process, and {@code r != null} in the906// child (system_server) process.907if(r!=null){908r.run();909return;910}911}912913Log.i(TAG,"Accepting command socket connections");914915// The select loop returns early in the child process after a fork and916// loops forever in the zygote.917caller=zygoteServer.runSelectLoop(abiList);918}catch(Throwableex){919Log.e(TAG,"System zygote died with exception",ex);920throwex;921}finally{922if(zygoteServer!=null){923zygoteServer.closeServerSocket();924}925}926927// We're in the child process and have exited the select loop. Proceed to execute the928// command.929if(caller!=null){930caller.run();931}932}
135staticvoidpreload(TimingsTraceLogbootTimingsTraceLog){138beginPreload();141preloadClasses();144cacheNonBootClasspathClassLoaders();147preloadResources();150nativePreloadAppProcessHALs();153maybePreloadGraphicsDriver();155preloadSharedLibraries();156preloadTextResources();157// Ask the WebViewFactory to do any initialization that must run in the zygote process,158// for memory sharing purposes.159WebViewFactory.prepareWebViewInZygote();160endPreload();161warmUpJcaProviders();164sPreloadComplete=true;165}......244/**
245 * Performs Zygote process initialization. Loads and initializes commonly used classes.
246 *
247 * Most classes only cause a few hundred bytes to be allocated, but a few will allocate a dozen
248 * Kbytes (in one case, 500+K).
249 */250privatestaticvoidpreloadClasses(){251finalVMRuntimeruntime=VMRuntime.getRuntime();252253InputStreamis;254try{255is=newFileInputStream(PRELOADED_CLASSES);256}catch(FileNotFoundExceptione){257Log.e(TAG,"Couldn't find "+PRELOADED_CLASSES+".");258return;259}260261Log.i(TAG,"Preloading classes...");262longstartTime=SystemClock.uptimeMillis();263264// Drop root perms while running static initializers.265finalintreuid=Os.getuid();266finalintregid=Os.getgid();267268// We need to drop root perms only if we're already root. In the case of "wrapped"269// processes (see WrapperInit), this function is called from an unprivileged uid270// and gid.271booleandroppedPriviliges=false;272if(reuid==ROOT_UID&®id==ROOT_GID){273try{274Os.setregid(ROOT_GID,UNPRIVILEGED_GID);275Os.setreuid(ROOT_UID,UNPRIVILEGED_UID);276}catch(ErrnoExceptionex){277thrownewRuntimeException("Failed to drop root",ex);278}279280droppedPriviliges=true;281}282283// Alter the target heap utilization. With explicit GCs this284// is not likely to have any effect.285floatdefaultUtilization=runtime.getTargetHeapUtilization();286runtime.setTargetHeapUtilization(0.8f);287288try{289BufferedReaderbr=290newBufferedReader(newInputStreamReader(is),Zygote.SOCKET_BUFFER_SIZE);291292intcount=0;293Stringline;294while((line=br.readLine())!=null){295// Skip comments and blank lines.296line=line.trim();297if(line.startsWith("#")||line.equals("")){298continue;299}300301Trace.traceBegin(Trace.TRACE_TAG_DALVIK,line);302try{303if(false){304Log.v(TAG,"Preloading "+line+"...");305}306// Load and explicitly initialize the given class. Use307// Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups308// (to derive the caller's class-loader). Use true to force initialization, and309// null for the boot classpath class-loader (could as well cache the310// class-loader of this class in a variable).311Class.forName(line,true,null);312count++;313}catch(ClassNotFoundExceptione){314Log.w(TAG,"Class not found for preloading: "+line);315}catch(UnsatisfiedLinkErrore){316Log.w(TAG,"Problem preloading "+line+": "+e);317}catch(Throwablet){318Log.e(TAG,"Error preloading "+line+".",t);319if(tinstanceofError){320throw(Error)t;321}322if(tinstanceofRuntimeException){323throw(RuntimeException)t;324}325thrownewRuntimeException(t);326}327Trace.traceEnd(Trace.TRACE_TAG_DALVIK);328}329330Log.i(TAG,"...preloaded "+count+" classes in "331+(SystemClock.uptimeMillis()-startTime)+"ms.");332}catch(IOExceptione){333Log.e(TAG,"Error reading "+PRELOADED_CLASSES+".",e);334}finally{335IoUtils.closeQuietly(is);336// Restore default.337runtime.setTargetHeapUtilization(defaultUtilization);338339// Fill in dex caches with classes, fields, and methods brought in by preloading.340Trace.traceBegin(Trace.TRACE_TAG_DALVIK,"PreloadDexCaches");341runtime.preloadDexCaches();342Trace.traceEnd(Trace.TRACE_TAG_DALVIK);343344// Bring back root. We'll need it later if we're in the zygote.345if(droppedPriviliges){346try{347Os.setreuid(ROOT_UID,ROOT_UID);348Os.setregid(ROOT_GID,ROOT_GID);349}catch(ErrnoExceptionex){350thrownewRuntimeException("Failed to restore root",ex);351}352}353}354}......382/**
383 * Load in commonly used resources, so they can be shared across processes.
384 *
385 * These tend to be a few Kbytes, but are frequently in the 20-40K range, and occasionally even
386 * larger.
387 */388privatestaticvoidpreloadResources(){389finalVMRuntimeruntime=VMRuntime.getRuntime();390391try{392mResources=Resources.getSystem();393mResources.startPreloading();394if(PRELOAD_RESOURCES){395Log.i(TAG,"Preloading resources...");396397longstartTime=SystemClock.uptimeMillis();398TypedArrayar=mResources.obtainTypedArray(399com.android.internal.R.array.preloaded_drawables);400intN=preloadDrawables(ar);401ar.recycle();402Log.i(TAG,"...preloaded "+N+" resources in "403+(SystemClock.uptimeMillis()-startTime)+"ms.");404405startTime=SystemClock.uptimeMillis();406ar=mResources.obtainTypedArray(407com.android.internal.R.array.preloaded_color_state_lists);408N=preloadColorStateLists(ar);409ar.recycle();410Log.i(TAG,"...preloaded "+N+" resources in "411+(SystemClock.uptimeMillis()-startTime)+"ms.");412413if(mResources.getBoolean(414com.android.internal.R.bool.config_freeformWindowManagement)){415startTime=SystemClock.uptimeMillis();416ar=mResources.obtainTypedArray(417com.android.internal.R.array.preloaded_freeform_multi_window_drawables);418N=preloadDrawables(ar);419ar.recycle();420Log.i(TAG,"...preloaded "+N+" resource in "421+(SystemClock.uptimeMillis()-startTime)+"ms.");422}423}424mResources.finishPreloading();425}catch(RuntimeExceptione){426Log.w(TAG,"Failure preloading resources",e);427}428}
48classZygoteServer{.......88/**
89 * Listening socket that accepts new server connections.
90 */91privateLocalServerSocketmZygoteSocket;......142/**
143 * Initialize the Zygote server with the Zygote server socket, USAP pool server socket, and USAP
144 * pool event FD.
145 *
146 * @param isPrimaryZygote If this is the primary Zygote or not.
147 */148ZygoteServer(booleanisPrimaryZygote){151if(isPrimaryZygote){152mZygoteSocket=Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);153mUsapPoolSocket=154Zygote.createManagedSocketFromInitSocket(155Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);156}else{157mZygoteSocket=Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);158mUsapPoolSocket=159Zygote.createManagedSocketFromInitSocket(160Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);161}166}......176/**
177 * Registers a server socket for zygote command connections. This opens the server socket
178 * at the specified name in the abstract socket namespace.
179 */180voidregisterServerSocketAtAbstractName(StringsocketName){181if(mZygoteSocket==null){182try{183mZygoteSocket=newLocalServerSocket(socketName);184mCloseSocketFd=false;185}catch(IOExceptionex){186thrownewRuntimeException(187"Error binding to abstract socket '"+socketName+"'",ex);188}189}190}......210/**
211 * Close and clean up zygote sockets. Called on shutdown and on the
212 * child's exit path.
213 */214voidcloseServerSocket(){215try{216if(mZygoteSocket!=null){217FileDescriptorfd=mZygoteSocket.getFileDescriptor();218mZygoteSocket.close();219if(fd!=null&&mCloseSocketFd){220Os.close(fd);221}222}223}catch(IOExceptionex){224Log.e(TAG,"Zygote: error closing sockets",ex);225}catch(ErrnoExceptionex){226Log.e(TAG,"Zygote: error closing descriptor",ex);227}228229mZygoteSocket=null;230}......368/**
369 * Runs the zygote process's select loop. Accepts new connections as
370 * they happen, and reads commands from connections one spawn-request's
371 * worth at a time.
372 */373RunnablerunSelectLoop(StringabiList){374ArrayList<FileDescriptor>socketFDs=newArrayList<FileDescriptor>();375ArrayList<ZygoteConnection>peers=newArrayList<ZygoteConnection>();376377socketFDs.add(mZygoteSocket.getFileDescriptor());378peers.add(null);379380while(true){381fetchUsapPoolPolicyPropsWithMinInterval();382383int[]usapPipeFDs=null;384StructPollfd[]pollFDs=null;385386// Allocate enough space for the poll structs, taking into account387// the state of the USAP pool for this Zygote (could be a388// regular Zygote, a WebView Zygote, or an AppZygote).389if(mUsapPoolEnabled){390usapPipeFDs=Zygote.getUsapPipeFDs();391pollFDs=newStructPollfd[socketFDs.size()+1+usapPipeFDs.length];392}else{393pollFDs=newStructPollfd[socketFDs.size()];394}395396/*
397 * For reasons of correctness the USAP pool pipe and event FDs
398 * must be processed before the session and server sockets. This
399 * is to ensure that the USAP pool accounting information is
400 * accurate when handling other requests like API blacklist
401 * exemptions.
402 */403404intpollIndex=0;405for(FileDescriptorsocketFD:socketFDs){406pollFDs[pollIndex]=newStructPollfd();407pollFDs[pollIndex].fd=socketFD;408pollFDs[pollIndex].events=(short)POLLIN;409++pollIndex;410}411412finalintusapPoolEventFDIndex=pollIndex;413414if(mUsapPoolEnabled){415pollFDs[pollIndex]=newStructPollfd();416pollFDs[pollIndex].fd=mUsapPoolEventFD;417pollFDs[pollIndex].events=(short)POLLIN;418++pollIndex;419420for(intusapPipeFD:usapPipeFDs){421FileDescriptormanagedFd=newFileDescriptor();422managedFd.setInt$(usapPipeFD);423424pollFDs[pollIndex]=newStructPollfd();425pollFDs[pollIndex].fd=managedFd;426pollFDs[pollIndex].events=(short)POLLIN;427++pollIndex;428}429}430431try{432Os.poll(pollFDs,-1);433}catch(ErrnoExceptionex){434thrownewRuntimeException("poll failed",ex);435}436437booleanusapPoolFDRead=false;438439while(--pollIndex>=0){440if((pollFDs[pollIndex].revents&POLLIN)==0){441continue;442}443444if(pollIndex==0){445// Zygote server socket446447ZygoteConnectionnewPeer=acceptCommandPeer(abiList);448peers.add(newPeer);449socketFDs.add(newPeer.getFileDescriptor());450451}elseif(pollIndex<usapPoolEventFDIndex){452// Session socket accepted from the Zygote server socket453454try{455ZygoteConnectionconnection=peers.get(pollIndex);456finalRunnablecommand=connection.processOneCommand(this);457458// TODO (chriswailes): Is this extra check necessary?459if(mIsForkChild){460// We're in the child. We should always have a command to run at this461// stage if processOneCommand hasn't called "exec".462if(command==null){463thrownewIllegalStateException("command == null");464}465466returncommand;467}else{468// We're in the server - we should never have any commands to run.469if(command!=null){470thrownewIllegalStateException("command != null");471}472473// We don't know whether the remote side of the socket was closed or474// not until we attempt to read from it from processOneCommand. This475// shows up as a regular POLLIN event in our regular processing loop.476if(connection.isClosedByPeer()){477connection.closeSocket();478peers.remove(pollIndex);479socketFDs.remove(pollIndex);480}481}482}catch(Exceptione){483if(!mIsForkChild){484// We're in the server so any exception here is one that has taken place485// pre-fork while processing commands or reading / writing from the486// control socket. Make a loud noise about any such exceptions so that487// we know exactly what failed and why.488489Slog.e(TAG,"Exception executing zygote command: ",e);490491// Make sure the socket is closed so that the other end knows492// immediately that something has gone wrong and doesn't time out493// waiting for a response.494ZygoteConnectionconn=peers.remove(pollIndex);495conn.closeSocket();496497socketFDs.remove(pollIndex);498}else{499// We're in the child so any exception caught here has happened post500// fork and before we execute ActivityThread.main (or any other main()501// method). Log the details of the exception and bring down the process.502Log.e(TAG,"Caught post-fork exception in child process.",e);503throwe;504}505}finally{506// Reset the child flag, in the event that the child process is a child-507// zygote. The flag will not be consulted this loop pass after the Runnable508// is returned.509mIsForkChild=false;510}511}else{512// Either the USAP pool event FD or a USAP reporting pipe.513514// If this is the event FD the payload will be the number of USAPs removed.515// If this is a reporting pipe FD the payload will be the PID of the USAP516// that was just specialized.517longmessagePayload=-1;518519try{520byte[]buffer=newbyte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];521intreadBytes=Os.read(pollFDs[pollIndex].fd,buffer,0,buffer.length);522523if(readBytes==Zygote.USAP_MANAGEMENT_MESSAGE_BYTES){524DataInputStreaminputStream=525newDataInputStream(newByteArrayInputStream(buffer));526527messagePayload=inputStream.readLong();528}else{529Log.e(TAG,"Incomplete read from USAP management FD of size "530+readBytes);531continue;532}533}catch(Exceptionex){534if(pollIndex==usapPoolEventFDIndex){535Log.e(TAG,"Failed to read from USAP pool event FD: "536+ex.getMessage());537}else{538Log.e(TAG,"Failed to read from USAP reporting pipe: "539+ex.getMessage());540}541542continue;543}544545if(pollIndex>usapPoolEventFDIndex){546Zygote.removeUsapTableEntry((int)messagePayload);547}548549usapPoolFDRead=true;550}551}552553// Check to see if the USAP pool needs to be refilled.554if(usapPoolFDRead){555int[]sessionSocketRawFDs=556socketFDs.subList(1,socketFDs.size())557.stream()558.mapToInt(fd->fd.getInt$())559.toArray();560561finalRunnablecommand=fillUsapPool(sessionSocketRawFDs);562563if(command!=null){564returncommand;565}566}567}568}569}
718/**
719 * Prepare the arguments and forks for the system server process.
720 *
721 * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
722 * process; {@code null} in the parent.
723 */724privatestaticRunnableforkSystemServer(StringabiList,StringsocketName,725ZygoteServerzygoteServer){726longcapabilities=posixCapabilitiesAsBits(727OsConstants.CAP_IPC_LOCK,728OsConstants.CAP_KILL,729OsConstants.CAP_NET_ADMIN,730OsConstants.CAP_NET_BIND_SERVICE,731OsConstants.CAP_NET_BROADCAST,732OsConstants.CAP_NET_RAW,733OsConstants.CAP_SYS_MODULE,734OsConstants.CAP_SYS_NICE,735OsConstants.CAP_SYS_PTRACE,736OsConstants.CAP_SYS_TIME,737OsConstants.CAP_SYS_TTY_CONFIG,738OsConstants.CAP_WAKE_ALARM,739OsConstants.CAP_BLOCK_SUSPEND740);741/* Containers run without some capabilities, so drop any caps that are not available. */742StructCapUserHeaderheader=newStructCapUserHeader(743OsConstants._LINUX_CAPABILITY_VERSION_3,0);744StructCapUserData[]data;745try{746data=Os.capget(header);747}catch(ErrnoExceptionex){748thrownewRuntimeException("Failed to capget()",ex);749}750capabilities&=((long)data[0].effective)|(((long)data[1].effective)<<32);751752/* Hardcoded command line to start the system server */753Stringargs[]={754"--setuid=1000",755"--setgid=1000",756"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"757+"1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",758"--capabilities="+capabilities+","+capabilities,759"--nice-name=system_server",760"--runtime-args",761"--target-sdk-version="+VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,762"com.android.server.SystemServer",763};764ZygoteArgumentsparsedArgs=null;765766intpid;767768try{769parsedArgs=newZygoteArguments(args);770Zygote.applyDebuggerSystemProperty(parsedArgs);771Zygote.applyInvokeWithSystemProperty(parsedArgs);772773booleanprofileSystemServer=SystemProperties.getBoolean(774"dalvik.vm.profilesystemserver",false);775if(profileSystemServer){776parsedArgs.mRuntimeFlags|=Zygote.PROFILE_SYSTEM_SERVER;777}778779/* Request to fork the system server process */780pid=Zygote.forkSystemServer(781parsedArgs.mUid,parsedArgs.mGid,782parsedArgs.mGids,783parsedArgs.mRuntimeFlags,784null,785parsedArgs.mPermittedCapabilities,786parsedArgs.mEffectiveCapabilities);787}catch(IllegalArgumentExceptionex){788thrownewRuntimeException(ex);789}790791/* For child process */792if(pid==0){793if(hasSecondZygote(abiList)){794waitForSecondaryZygote(socketName);795}796797zygoteServer.closeServerSocket();798returnhandleSystemServerProcess(parsedArgs);799}800801returnnull;802}