How is the Android App app started?

preface

As many years of Android development, I have written many applications, but how does an App start? If you want to say that the desktop starts at one click, that's right. But what about its startup process? With such questions, let's study step by step.

Android startup process

Generally, on any platform, the following components will be loaded and executed step by step:

  • Boot loader
  • U-boot (optional)
  • Kernel
  • Android

Android processes have the following order:

  • Init
  • Zygote
  • System Server
  • Service Manager
  • Other Daemons and processes
  • Applications

The specific situation is shown in the figure below. It is interesting to combine the two pictures:

  • Boot ROM: when the power supply is pressed, the boot chip code will be executed from the predefined place (solidified in ROM), load the boot program BootLoader to RAM, and then execute. (this step is designed and implemented by the "chip manufacturer")

  • Boot loader: Bootloader starts to execute. First, it is responsible for completing hardware initialization and booting the operating system. (this step is designed and implemented by the "equipment manufacturer")

  • Kernel: the Linux kernel is the core of Android, responsible for process creation, inter process communication, device driver, file system management, etc. Android applies custom patches on the mainstream kernel to support some functions required for Android operation, such as wake-up lock. The kernel can be loaded as an uncompressed image or a compressed image. When loaded, it mounts the root file system (usually passed as a kernel command-line parameter) and starts the first application in user space. (this step is what needs to be involved in the Android kernel development process)

  • Android: the Linux kernel startup process of Android system and major Linux distributions is similar. The biggest difference between them lies in the difference of init program, because init program determines which daemons and services the system will start and what kind of user UI interface it presents during startup.

Therefore, init program is the core program for analyzing the Android startup process.

  • Init and init.rc: the first user space application executed when starting the kernel is the init executable located in the root folder. This process parses the startup script called the "init. RC" script. This is written in a language specially designed for android. It is used to start all necessary processes, daemons and services for android to run normally. It provides various types of execution time, such as early init, on boot, on post FS, etc. (the ancestor of user space)

  • Demons and Services: init process creates various daemons and processes, such as rild, vold, mediaserver, adb, etc. each process is responsible for its own functions. The description of these processes is beyond the scope of this article. Instead, we will talk more about the "Zygote" process.

  • Service Manager: the service manager process manages all services running in the system. Each service created registers itself in this process, and this information is for future reference by other processes / applications.

  • Zygote: zygote is one of the first init processes created at startup. The term "zygote" is based on biology "the initial cell division formed to produce offspring". Similarly, "zygote in android" initializes Dalivik VM(ART) and fork to create multiple instances to support each Android process. It helps to use shared code between VM instances, thus reducing memory consumption and loading time. It is very suitable for embedded systems. In addition to installing listeners on the server socket, zygote preloads classes and resources for later use in Android applications. When finished, the system server starts.

  • System Server: the System Server process starts all services available in Android.

In this article, we focus on starting from init to application startup.

1. What is Zygote

In Android, zygote is the name of a process. Android is based on the Linux System. When your mobile phone starts up, the Linux kernel will start a process called "init" after loading. In the Linux System, all processes are fork ed out by the init process, and our zygote process is no exception.

Zygote is not only a virtual machine process, but also an incubator of virtual machine instances. Whenever the system requires the execution of an Android application, zygote will fork (split) a sub process to execute the application.

1.1 app_main.cpp

frameworks/base/cmds/app_process/app_main.cpp

After Zygote is started, app_main.cpp will be executed. Whether it is C/c++/java, their entry is main(), just like when we see the Activity, we can directly find the onCreate() method.

1.1.1 main()

int main(int argc, char* const argv[])
{
    ...
    //Note 1: initialize AppRuntime(AndroidRunTime)
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        //Note 2: set zygote mode
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } 
        ...
    }
    Vector<String8> args;
    if (!className.isEmpty()) {
        ...
    } else {
        // We are in zygote mode.
        maybeCreateDalvikCache();

        // Note 3: in zygote mode, pass the parameter to the ZygoteInit.main() method.
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        //PROP_VALUE_MAX = 92;
        char prop[PROP_VALUE_MAX];
        ...
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }    
    if (zygote) {
        //Note 4: call the AndroidRuntime.start() method
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        ...
    } else {
        ...
    }
}

Note 1: initializing AppRuntime is actually Android runtime (Art).

Note 2: set zygote mode.

Note 3: pass the parameter to the ZygoteInit.main() method.

Note 4: start ZygoteInit. ZygoteInit here is the startup class of zygote process. This is discussed below. Let's take a look at the start() method of Android runtime first.

1.2 AndroidRuntime.cpp

frameworks/base/core/jni/AndroidRuntime.cpp

Android virtual machine

1.2.1 start()

/*
 * Start the Android runtime.  This involves starting the virtual machine and calling the "static void main(String[] args)" method in the class named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ...
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //Note 1: start the virtual machine
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    //Note 2: register Android features (JNI)
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    ...
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    ...
    /*
     * Start the virtual machine. This thread becomes the main thread of the VM and will not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ...
    } else {
        ...
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ...
        } else {
            //Note 3
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
        }
    }
    ...
}
Copy code

Note 1: start VM (virtual machine)

Note 2: register Android features (JNI)

Note 3: use JNI to call the main() method of zygotelnit. Zygotelnit here is a class file, that is, it has entered the java field from here.

JNI: a bridge connecting the native(C/C + +) layer and the java layer.

1.3 ZygoteInit.java

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

/**
 * zygote The startup class of the process.
 */
public class ZygoteInit {
    ...
}
Copy code

This is the entry point for the Zygote process. It creates Zygote services, loads resources, and handles other tasks related to the process of preparing to fork into the application.

1.3.1 main()

    @UnsupportedAppUsage
    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;

        try {
            ...
            boolean startSystemServer = false;
            //argv: command line parameter used to specify Zygote configuration.
            ...
            if (!enableLazyPreload) {
                //Note 1: preload resources.
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }
            ...
            //Note 2: create the LocalServerSocket of Zygote.
            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                //Note 3: start fork ing our system server process.
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                ...
            }
            ...
            // Note 4: zygote permanent cycle.
            caller = zygoteServer.runSelectLoop(abiList);            
        } catch (Throwable ex) {
            ...
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
        ...
    }
Copy code

Note 1: preload resources.

Note 2: create the LocalServerSocket of Zygote.

Note 3: start fork ing our system server process.

Note 4: zygote permanent cycle.

Let's take a look at forksystem server ();

1.3.2 forkSystemServer()

    /**
     * Prepare the arguments and forks for the system server process.
     *
     * @return A {@code Runnable} that provides an entrypoint into system_server code in the child
     * process; {@code null} in the parent.
     */
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...
        //Command line to start system server
        //The argv in ZygoteInit.main(String argv []) is similar to this
        String[] args = {
                "--setuid=1000",
                "--setgid=1000",
                "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                        + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        //Handle parameter parsing of args related to zygote spawner.
        ZygoteArguments parsedArgs;
        int pid;
        try {
            ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
            try {
                parsedArgs = ZygoteArguments.getInstance(commandBuffer);
            } catch (EOFException e) {
                throw new AssertionError("Unexpected argument error for forking system server", e);
            }
            commandBuffer.close();
            ...

            //Request fork system server process
            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }
Copy code

A system server is started here. Let's take a look at it.

2,SystemServer

System server is also called system server. SystemServer is also a process, including 92 services such as ActivityTaskManagerService, ActivityManagerService, PackageManagerService and WindowManagerService.

There are two very important processes in the Android Framework:

  • SystemServer process.

  • Zygote process.

2.1 SystemServer.java

frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer {
    ...
}
Copy code

2.1.1 main()

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
        ...
    }    
Copy code

Let's see what is used in run()?

2.1.2 run()

    private void run() {
        try {
            ...
            // Note 1: load the dynamic library libandroid_service.so. 
            System.loadLibrary("android_servers");

            // Note 2: create a system context.
            createSystemContext();

            // Call the mainline module initialization of each process.
            ActivityThread.initializeMainlineModules();

            // Note 3: create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Preparing a thread pool for parallelizable init tasks
            SystemServerInitThreadPool.start();
            ...
        } finally {

        }
        // Note 4: Start services.
        try {
            //Let's take a look at what services are started by these three methods
            startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);
        } catch (Throwable ex) {
            ...
        } finally {
            t.traceEnd(); // StartServices
        }

        ...
        // Note 5: Loop permanent Loop.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

Copy code

Note 1: load the dynamic library libandroid_service.so.

Note 2: create a system context.

Note 3: create the system service manager.

Note 4: start services (startBootstrapServices, startCoreServices, startOtherServices)

Note 5: Loop permanent Loop.

2.1.3 createSystemContext()

    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);

        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }
Copy code

Initialize the system context object mSystemContext and set the default theme. mSystemContext is actually a Context(ContextImpl) object.

When you call ActivityThread.systemMain(), you will call ActivityThread.attach(true). In attach(), you create an Application object and call Application.onCreate().

2.1.4 startBootstrapServices()

    /**
     * Start the system boot service. Because these services have complex interdependencies, they are all placed in this method.
     */
    private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
        ...
        final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
        SystemServerInitThreadPool.submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);

        // Platformcompact service is used by ActivityManagerService, PackageManagerService and other services
        PlatformCompat platformCompat = new PlatformCompat(mSystemContext);
        ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
        ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE,
                new PlatformCompatNative(platformCompat));
        AppCompatCallbacks.install(new long[0]);

        mSystemServiceManager.startService(FileIntegrityService.class);
        Installer installer = mSystemServiceManager.startService(Installer.class);
        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
        mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
        startMemtrackProxyService();

        // StartActivityManager
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        //Initialize ActivityManagerService
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm);
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        mWindowManagerGlobalLock = atm.getGlobalLock();

        mDataLoaderManagerService = mSystemServiceManager.startService(
                DataLoaderManagerService.class);

        mIncrementalServiceHandle = startIncrementalService();
        t.traceEnd();

        //To initialize powermanagerservice, you need to start it in advance because other services need it.
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
        mSystemServiceManager.startService(ThermalManagerService.class);

        // The power management has been turned on, and the ActivityManagerService is responsible for the power management function
        mActivityManagerService.initPowerManagement();

        mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
        ...

        mSystemServiceManager.startService(LightsService.class);

        // Package manager isn't started yet; need to use SysProp not hardware feature
        if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
            mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
        }

        // Initialize displaymanagerservice
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

        mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

        // Start the package manager.
        try {
            mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
        } finally {

        }

        // Now that the PackageManagerService has started, register the dex load reporter to capture any dex files loaded by the system service.
        // These dex files will be optimized by the BackgroundDexOptService.
        SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);

        mFirstBoot = mPackageManagerService.isFirstBoot();
        mPackageManager = mSystemContext.getPackageManager();
        ...
        //Add AMS, etc. to ServiceManager
        mActivityManagerService.setSystemProcess();
        if (!mOnlyCore) {
            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                    false);
            if (!disableOtaDexopt) {
                try {
                    OtaDexoptService.main(mSystemContext, mPackageManagerService);
                } catch (Throwable e) {

                } finally {
                }
            }
        }

        ...
        mSensorServiceStart = SystemServerInitThreadPool.submit(() -> {
            TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog();
            startSensorService();
        }, START_SENSOR_SERVICE);

        // startBootstrapServices
    }
Copy code

Major changes:

  • Activity task manager service (ATMS): responsible for managing activities and processes, including lifecycle and state switching.

  • ActivityManagerService(AMS): a subclass of AMN, which is responsible for managing three components (except Activity) and processes, including life cycle and state switching. AMS is extremely complex because it interacts with the ui, involving window.

ActivityTaskManagerService: it is generated by stripping Activity related content from ActivityManagerService.

PowerManagerService(PMS): power management service.

Package manager service (PKMs): package management service, not called PMS, is to distinguish it from power management service.

2.1.5 startCoreServices()

    /**
     * Start the core service.
     */
    private void startCoreServices(@NonNull TimingsTraceAndSlog t) {
        // Service for system config
        mSystemServiceManager.startService(SystemConfigService.class);
        // Tracks the battery level.  Requires LightService.
        mSystemServiceManager.startService(BatteryService.class);
        ...
        mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);

        mSystemServiceManager.startService(ROLLBACK_MANAGER_SERVICE_CLASS);

        mSystemServiceManager.startService(NativeTombstoneManagerService.class);

        mSystemServiceManager.startService(BugreportManagerService.class);

        mSystemServiceManager.startService(GpuService.class);

        // startCoreServices
    }

Copy code

2.1.6 startOtherServices()

    /**
     * Start other services.
     */
    private void startOtherServices(@NonNull TimingsTraceAndSlog t) {

        final Context context = mSystemContext;
        VibratorService vibrator = null;
        DynamicSystemService dynamicSystem = null;
        IStorageManager storageManager = null;
        NetworkManagementService networkManagement = null;
        IpSecService ipSecService = null;
        VpnManagerService vpnManager = null;
        VcnManagementService vcnManagement = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        NsdService serviceDiscovery = null;
        WindowManagerService wm = null;
        SerialService serial = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        MmsServiceBroker mmsService = null;
        HardwarePropertiesManagerService hardwarePropertiesService = null;
        PacProxyService pacProxyService = null;
        ...
        // Now you can start to launch the third-party APP application (such as Launcher desktop)
        mActivityManagerService.systemReady(() -> {
        ...
         }, t);       
        // startOtherServices
    }
Copy code

After the above steps, when we call createSystemContext() to create the system context, we have also completed the creation of mSystemContext and ActivityThread.

ATMS, AMS, WMS, PKMS and other objects have been created, and the initialization of member variables has been completed.

Note: This is the process when the system process is started. After that, the system will be started

Launcher program to complete the loading and display of the system interface.

In the framework design of Android, the server side refers to the system services shared by all apps, such as ATMS, AMS, WMS, PKMS and so on. These basic system services are shared by all apps.

3. What is Launcher

In the Android system, the application is started by the Launcher. In fact, the Launcher itself is also an application. After other applications are installed, a corresponding icon will appear on the Launcher interface. When you click this icon, the Launcher will start the corresponding application.

Of course, you can also start the application in other applications. But it is essentially a call to startActivity().

3.1 LauncherActivity.java

frameworks/base/core/java/android/app/LauncherActivity.java

/**
 * Displays a list of all activities which can be performed
 * for a given intent. Launches when clicked.
 *
 * @deprecated Applications can implement this UI themselves using
 *   {@link androidx.recyclerview.widget.RecyclerView} and
 *   {@link android.content.pm.PackageManager#queryIntentActivities(Intent, int)}
 */
@Deprecated
public abstract class LauncherActivity extends ListActivity {
    ...
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Intent intent = intentForPosition(position);
        startActivity(intent);
    }
}
Copy code

Summary

A whole drawing is attached

You can take a direct look at what you know about startActivity(). There are too many contents in this article. I'm worried about it myself. I've never seen a wave of attention. The details will be in the next article: ❤️ Android startActivity source code analysis ❤️ Explain in.

Tags: Linux Android Design Pattern Framework

Posted on Mon, 11 Oct 2021 15:35:54 -0400 by dwilson