chromium/content/public/android/java/src/org/chromium/content_public/app/ZygotePreload.java

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.content_public.app;

import android.annotation.SuppressLint;
import android.content.pm.ApplicationInfo;
import android.os.Build;
import android.os.Process;
import android.os.SystemClock;

import androidx.annotation.RequiresApi;

import org.chromium.base.Log;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.process_launcher.ChildProcessService;
import org.chromium.base.version_info.VersionConstants;
import org.chromium.build.BuildConfig;

/**
 * Class used in android:zygotePreloadName attribute of manifest.
 * Code in this class runs in the zygote. It runs in a limited environment
 * (eg no application) and cannot communicate with any other app process,
 * so care must be taken when writing code in this class. Eg it should not
 * create any thread.
 */
@RequiresApi(Build.VERSION_CODES.Q)
public class ZygotePreload implements android.app.ZygotePreload {
    private static final String TAG = "ZygotePreload";

    @SuppressLint("Override")
    @Override
    public void doPreload(ApplicationInfo appInfo) {
        // APKs targeting pre-Q releases, like ChromePublic, have ZygotePreload in their manifests.
        // Running Chrome from these APKs on Q+ creates the app zygote and performs the preload. In
        // order to load the native library with the correct name prefix, the "linker
        // implementation" is chosen by the LibraryLoader itself, and not overwritten here.
        doPreloadCommon(appInfo);
    }

    protected final void doPreloadCommon(ApplicationInfo appInfo) {
        Log.i(
                TAG,
                "version=%s (%s) minSdkVersion=%s isBundle=%s",
                VersionConstants.PRODUCT_VERSION,
                BuildConfig.VERSION_CODE,
                BuildConfig.MIN_SDK_VERSION,
                BuildConfig.BUNDLES_SUPPORTED);
        try {
            // The current thread time is the best approximation we have of the zygote start time
            // since Process.getStartUptimeMillis() is not reliable in the zygote process. This will
            // be the total CPU time the current thread has been running, and is reset on fork so
            // should give an accurate measurement of zygote process startup time.
            ChildProcessService.setZygoteInfo(
                    Process.myPid(), SystemClock.currentThreadTimeMillis());
            LibraryLoader.getInstance().getMediator().initInAppZygote();
            LibraryLoader.getInstance().loadNowInZygote(appInfo);
        } catch (Throwable e) {
            // Ignore any exception. Child service can continue loading.
            Log.w(TAG, "Exception in zygote", e);
        }
    }
}