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

package org.chromium.content.browser;

import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.text.TextUtils;

import org.chromium.base.ContextUtils;
import org.chromium.base.CpuFeatures;
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.TraceEvent;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.base.annotations.SuppressFBWarnings;
import org.chromium.base.library_loader.Linker;
import org.chromium.base.process_launcher.ChildProcessConstants;
import org.chromium.base.process_launcher.ChildProcessCreationParams;
import org.chromium.base.process_launcher.FileDescriptorInfo;
import org.chromium.content.app.ChromiumLinkerParams;
import org.chromium.content.app.SandboxedProcessService;
import org.chromium.content.common.ContentSwitches;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * This is the java counterpart to ChildProcessLauncherHelper. It is owned by native side and
 * has an explicit destroy method.
 * Each public or jni methods should have explicit documentation on what threads they are called.
 */
@JNINamespace("content::internal")
public class ChildProcessLauncherHelper {
    private static final String TAG = "ChildProcLH";

    // Manifest values used to specify the service names.
    private static final String NUM_SANDBOXED_SERVICES_KEY =
            "org.chromium.content.browser.NUM_SANDBOXED_SERVICES";
    private static final String SANDBOXED_SERVICES_NAME_KEY =
            "org.chromium.content.browser.SANDBOXED_SERVICES_NAME";
    private static final String NUM_PRIVILEGED_SERVICES_KEY =
            "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES";
    private static final String PRIVILEGED_SERVICES_NAME_KEY =
            "org.chromium.content.browser.PRIVILEGED_SERVICES_NAME";

    // Represents an invalid process handle; same as base/process/process.h kNullProcessHandle.
    private static final int NULL_PROCESS_HANDLE = 0;

    // Delay between the call to freeConnection and the connection actually beeing freed.
    private static final long FREE_CONNECTION_DELAY_MILLIS = 1;

    // Factory used by the SpareConnection to create the actual ChildProcessConnection.
    private static final SpareChildConnection.ConnectionFactory SANDBOXED_CONNECTION_FACTORY =
            new SpareChildConnection.ConnectionFactory() {
                @Override
                public ChildProcessConnection allocateBoundConnection(Context context,
                        ChildProcessCreationParams creationParams,
                        ChildProcessConnection.ServiceCallback serviceCallback) {
                    boolean bindToCallerCheck =
                            creationParams == null ? false : creationParams.getBindToCallerCheck();
                    ChildConnectionAllocator allocator =
                            getConnectionAllocator(context, creationParams, true /* sandboxed */);
                    Bundle serviceBundle =
                            ChildProcessLauncherHelper.createServiceBundle(bindToCallerCheck);
                    return allocator.allocate(context, serviceBundle, serviceCallback);
                }
            };

    // A warmed-up connection to a sandboxed service.
    private static SpareChildConnection sSpareSandboxedConnection;

    // Map from package name to ChildConnectionAllocator.
    private static final Map<String, ChildConnectionAllocator>
            sSandboxedChildConnectionAllocatorMap = new HashMap<>();

    // Allocator used for non-sandboxed services.
    private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator;

    // Used by tests to override the default sandboxed service allocator settings.
    private static ChildConnectionAllocator.ConnectionFactory sSandboxedServiceFactoryForTesting;
    private static int sSandboxedServicesCountForTesting = -1;
    private static String sSandboxedServicesNameForTesting;

    // Map from PID to ChildService connection.
    private static Map<Integer, ChildProcessLauncherHelper> sLauncherByPid = new HashMap<>();

    // Manages OOM bindings used to bind chind services. Lazily initialized by getBindingManager().
    private static BindingManager sBindingManager;

    // Whether the main application is currently brought to the foreground.
    private static boolean sApplicationInForeground = true;

    // The IBinder provided to the created service.
    private final IBinder mIBinderCallback;

    // Whether the connection should be setup once connected. Tests can set this to false to
    // simulate a connected but not yet setup connection.
    private final boolean mDoSetupConnection;

    private final ChildProcessCreationParams mCreationParams;

    private final String[] mCommandLine;

    private final FileDescriptorInfo[] mFilesToBeMapped;

    // The allocator used to create the connection.
    private final ChildConnectionAllocator mConnectionAllocator;

    // Whether the created process should be sandboxed.
    private final boolean mSandboxed;

    // Note native pointer is only guaranteed live until nativeOnChildProcessStarted.
    private long mNativeChildProcessLauncherHelper;

    // The actual service connection. Set once we have connected to the service.
    private ChildProcessConnection mConnection;

    @CalledByNative
    private static FileDescriptorInfo makeFdInfo(
            int id, int fd, boolean autoClose, long offset, long size) {
        assert LauncherThread.runningOnLauncherThread();
        ParcelFileDescriptor pFd;
        if (autoClose) {
            // Adopt the FD, it will be closed when we close the ParcelFileDescriptor.
            pFd = ParcelFileDescriptor.adoptFd(fd);
        } else {
            try {
                pFd = ParcelFileDescriptor.fromFd(fd);
            } catch (IOException e) {
                Log.e(TAG, "Invalid FD provided for process connection, aborting connection.", e);
                return null;
            }
        }
        return new FileDescriptorInfo(id, pFd, offset, size);
    }

    @VisibleForTesting
    @CalledByNative
    public static ChildProcessLauncherHelper createAndStart(long nativePointer, int paramId,
            String[] commandLine, FileDescriptorInfo[] filesToBeMapped) {
        assert LauncherThread.runningOnLauncherThread();
        ChildProcessCreationParams creationParams = ChildProcessCreationParams.get(paramId);
        if (paramId != ChildProcessCreationParams.DEFAULT_ID && creationParams == null) {
            throw new RuntimeException("CreationParams id " + paramId + " not found");
        }

        String processType =
                ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWITCH_PROCESS_TYPE);

        boolean sandboxed = true;
        if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) {
            if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) {
                sandboxed = false;
            } else {
                // We only support sandboxed utility processes now.
                assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType);
            }
        }

        IBinder binderCallback = ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)
                ? new GpuProcessCallback()
                : null;

        ChildProcessLauncherHelper process_launcher =
                new ChildProcessLauncherHelper(nativePointer, creationParams, commandLine,
                        filesToBeMapped, sandboxed, binderCallback, true /* doSetupConnection */);
        process_launcher.start();
        return process_launcher;
    }

    /**
     * Creates a ready to use sandboxed child process. Should be called early during startup so the
     * child process is created while other startup work is happening.
     * @param context the application context used for the connection.
     */
    public static void warmUp(final Context context) {
        assert ThreadUtils.runningOnUiThread();
        LauncherThread.post(new Runnable() {
            @Override
            public void run() {
                if (sSpareSandboxedConnection != null && !sSpareSandboxedConnection.isEmpty()) {
                    return;
                }
                sSpareSandboxedConnection =
                        new SpareChildConnection(context, SANDBOXED_CONNECTION_FACTORY,
                                ChildProcessCreationParams.getDefault(), true /* sandboxed */);
            }
        });
    }

    public static String getPackageNameFromCreationParams(
            Context context, ChildProcessCreationParams params, boolean sandboxed) {
        return (sandboxed && params != null) ? params.getPackageNameForSandboxedService()
                                             : context.getPackageName();
    }

    public static boolean isServiceExternalFromCreationParams(
            ChildProcessCreationParams params, boolean sandboxed) {
        return sandboxed && params != null && params.getIsSandboxedServiceExternal();
    }

    /**
     * Starts the moderate binding management that adjust a process priority in response to various
     * signals (app sent to background/foreground for example).
     * Note: WebAPKs and non WebAPKs share the same moderate binding pool, so the size of the
     * shared moderate binding pool is always set based on the number of sandboxes processes
     * used by Chrome.
     * @param context Android's context.
     */
    public static void startModerateBindingManagement(final Context context) {
        assert ThreadUtils.runningOnUiThread();
        LauncherThread.post(new Runnable() {
            @Override
            public void run() {
                ChildConnectionAllocator allocator = getConnectionAllocator(
                        context, ChildProcessCreationParams.getDefault(), true /* sandboxed */);
                getBindingManager().startModerateBindingManagement(
                        context, allocator.getNumberOfServices());
            }
        });
    }

    // Lazy initialize sBindingManager
    // TODO(boliu): This should be internal to content.
    @SuppressFBWarnings("LI_LAZY_INIT_STATIC") // Method is single thread.
    public static BindingManager getBindingManager() {
        assert LauncherThread.runningOnLauncherThread();
        if (sBindingManager == null) {
            sBindingManager = BindingManagerImpl.createBindingManager();
        }
        return sBindingManager;
    }

    /**
     * Called when the embedding application is sent to background.
     */
    public static void onSentToBackground() {
        assert ThreadUtils.runningOnUiThread();
        sApplicationInForeground = false;
        LauncherThread.post(new Runnable() {
            @Override
            public void run() {
                getBindingManager().onSentToBackground();
            }
        });
    }

    /**
     * Called when the embedding application is brought to foreground.
     */
    public static void onBroughtToForeground() {
        assert ThreadUtils.runningOnUiThread();
        sApplicationInForeground = true;
        LauncherThread.post(new Runnable() {
            @Override
            public void run() {
                getBindingManager().onBroughtToForeground();
            }
        });
    }

    @VisibleForTesting
    public static void setSandboxServicesSettingsForTesting(
            ChildConnectionAllocator.ConnectionFactory factory, int serviceCount,
            String serviceName) {
        sSandboxedServiceFactoryForTesting = factory;
        sSandboxedServicesCountForTesting = serviceCount;
        sSandboxedServicesNameForTesting = serviceName;
    }

    @VisibleForTesting
    public static void setBindingManagerForTesting(BindingManager manager) {
        sBindingManager = manager;
    }

    @VisibleForTesting
    static ChildConnectionAllocator getConnectionAllocator(
            Context context, ChildProcessCreationParams creationParams, boolean sandboxed) {
        assert LauncherThread.runningOnLauncherThread();
        final String packageName =
                getPackageNameFromCreationParams(context, creationParams, sandboxed);
        boolean bindAsExternalService =
                isServiceExternalFromCreationParams(creationParams, sandboxed);

        if (!sandboxed) {
            if (sPrivilegedChildConnectionAllocator == null) {
                sPrivilegedChildConnectionAllocator =
                        ChildConnectionAllocator.create(context, creationParams, packageName,
                                PRIVILEGED_SERVICES_NAME_KEY, NUM_PRIVILEGED_SERVICES_KEY,
                                bindAsExternalService, true /* useStrongBinding */);
            }
            return sPrivilegedChildConnectionAllocator;
        }

        if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageName)) {
            Log.w(TAG,
                    "Create a new ChildConnectionAllocator with package name = %s,"
                            + " sandboxed = true",
                    packageName);
            ChildConnectionAllocator connectionAllocator = null;
            if (sSandboxedServicesCountForTesting != -1) {
                // Testing case where allocator settings are overriden.
                String serviceName = !TextUtils.isEmpty(sSandboxedServicesNameForTesting)
                        ? sSandboxedServicesNameForTesting
                        : SandboxedProcessService.class.getName();
                connectionAllocator = ChildConnectionAllocator.createForTest(creationParams,
                        packageName, serviceName, sSandboxedServicesCountForTesting,
                        bindAsExternalService, false /* useStrongBinding */);
            } else {
                connectionAllocator = ChildConnectionAllocator.create(context, creationParams,
                        packageName, SANDBOXED_SERVICES_NAME_KEY, NUM_SANDBOXED_SERVICES_KEY,
                        bindAsExternalService, false /* useStrongBinding */);
            }
            if (sSandboxedServiceFactoryForTesting != null) {
                connectionAllocator.setConnectionFactoryForTesting(
                        sSandboxedServiceFactoryForTesting);
            }
            sSandboxedChildConnectionAllocatorMap.put(packageName, connectionAllocator);
            final ChildConnectionAllocator finalConnectionAllocator = connectionAllocator;
            // Tracks connections removal so the allocator can be freed when no longer used.
            connectionAllocator.addListener(new ChildConnectionAllocator.Listener() {
                @Override
                public void onConnectionAllocated(
                        ChildConnectionAllocator allocator, ChildProcessConnection connection) {
                    assert connection != null;
                    if (!allocator.isFreeConnectionAvailable()) {
                        // Proactively releases all the moderate bindings once all the sandboxed
                        // services are allocated, which will be very likely to have some of them
                        // killed by OOM killer.
                        getBindingManager().releaseAllModerateBindings();
                    }
                }

                @Override
                public void onConnectionFreed(
                        ChildConnectionAllocator allocator, ChildProcessConnection connection) {
                    assert allocator == finalConnectionAllocator;
                    if (!allocator.anyConnectionAllocated()) {
                        // Last connection was freed, the allocator is going aways, remove the
                        // listener.
                        allocator.removeListener(this);
                        ChildConnectionAllocator removedAllocator =
                                sSandboxedChildConnectionAllocatorMap.remove(packageName);
                        assert removedAllocator == allocator;
                    }
                }
            });
        }
        return sSandboxedChildConnectionAllocatorMap.get(packageName);
    }

    private ChildProcessLauncherHelper(long nativePointer,
            ChildProcessCreationParams creationParams, String[] commandLine,
            FileDescriptorInfo[] filesToBeMapped, boolean sandboxed, IBinder binderCallback,
            boolean doSetupConnection) {
        assert LauncherThread.runningOnLauncherThread();

        mCreationParams = creationParams;
        mCommandLine = commandLine;
        mFilesToBeMapped = filesToBeMapped;
        mNativeChildProcessLauncherHelper = nativePointer;
        mIBinderCallback = binderCallback;
        mDoSetupConnection = doSetupConnection;
        mSandboxed = sandboxed;

        mConnectionAllocator = getConnectionAllocator(
                ContextUtils.getApplicationContext(), mCreationParams, sandboxed);

        initLinker();
    }

    private void start() {
        assert LauncherThread.runningOnLauncherThread();
        assert mConnection == null;
        try {
            TraceEvent.begin("ChildProcessLauncher.start");

            ChildProcessConnection.ServiceCallback serviceCallback =
                    new ChildProcessConnection.ServiceCallback() {
                        @Override
                        public void onChildStarted() {}

                        @Override
                        public void onChildStartFailed() {
                            assert LauncherThread.runningOnLauncherThread();
                            Log.e(TAG, "ChildProcessConnection.start failed, trying again");
                            LauncherThread.post(new Runnable() {
                                @Override
                                public void run() {
                                    // The child process may already be bound to another client
                                    // (this can happen if multi-process WebView is used in more
                                    // than one process), so try starting the process again.
                                    // This connection that failed to start has not been freed,
                                    // so a new bound connection will be allocated.
                                    mConnection = null;
                                    start();
                                }
                            });
                        }

                        @Override
                        public void onChildProcessDied(ChildProcessConnection connection) {
                            assert LauncherThread.runningOnLauncherThread();
                            assert mConnection == connection;
                            ChildProcessLauncherHelper.this.onChildProcessDied();
                        }
                    };

            // Try to use the spare connection if there's one.
            if (sSpareSandboxedConnection != null) {
                mConnection = sSpareSandboxedConnection.getConnection(
                        mCreationParams, mSandboxed, serviceCallback);
                if (mConnection != null) {
                    Log.d(TAG, "Using warmed-up connection for service %s.",
                            mConnection.getServiceName());
                    // Clear the spare connection now that it's been used.
                    sSpareSandboxedConnection = null;
                }
            }

            allocateAndSetupConnection(serviceCallback);
        } finally {
            TraceEvent.end("ChildProcessLauncher.start");
        }
    }

    // Allocates a new connection and calls setUp on it.
    // If there are no available connections, it will retry when one becomes available.
    private boolean allocateAndSetupConnection(
            final ChildProcessConnection.ServiceCallback serviceCallback) {
        if (mConnection == null) {
            final Context context = ContextUtils.getApplicationContext();
            boolean bindToCallerCheck =
                    mCreationParams == null ? false : mCreationParams.getBindToCallerCheck();
            Bundle serviceBundle = createServiceBundle(bindToCallerCheck);
            onBeforeConnectionAllocated(serviceBundle);

            boolean useBindingManager = mSandboxed;
            mConnection = mConnectionAllocator.allocate(context, serviceBundle, serviceCallback);
            if (mConnection == null) {
                // No connection is available at this time. Add a listener so when one becomes
                // available we can create the service.
                mConnectionAllocator.addListener(new ChildConnectionAllocator.Listener() {
                    @Override
                    public void onConnectionAllocated(ChildConnectionAllocator allocator,
                            ChildProcessConnection connection) {}

                    @Override
                    public void onConnectionFreed(
                            ChildConnectionAllocator allocator, ChildProcessConnection connection) {
                        assert allocator == mConnectionAllocator;
                        if (!allocator.isFreeConnectionAvailable()) return;
                        allocator.removeListener(this);
                        boolean success = allocateAndSetupConnection(serviceCallback);
                        assert success;
                    }
                });
                return false;
            }
        }

        assert mConnection != null;
        Bundle connectionBundle = createConnectionBundle();
        onConnectionBound(mConnection, mConnectionAllocator, connectionBundle);

        if (mDoSetupConnection) {
            setupConnection(connectionBundle);
        }
        return true;
    }

    private void setupConnection(Bundle connectionBundle) {
        ChildProcessConnection.ConnectionCallback connectionCallback =
                new ChildProcessConnection.ConnectionCallback() {
                    @Override
                    public void onConnected(ChildProcessConnection connection) {
                        assert mConnection == connection;
                        onChildProcessStarted();
                    }
                };
        mConnection.setupConnection(connectionBundle, getIBinderCallback(), connectionCallback);
    }

    private void onChildProcessStarted() {
        assert LauncherThread.runningOnLauncherThread();

        int pid = mConnection.getPid();
        Log.d(TAG, "on connect callback, pid=%d", pid);

        onConnectionEstablished(mConnection);

        sLauncherByPid.put(pid, this);

        // Proactively close the FDs rather than waiting for the GC to do it.
        try {
            for (FileDescriptorInfo fileInfo : mFilesToBeMapped) {
                fileInfo.fd.close();
            }
        } catch (IOException ioe) {
            Log.w(TAG, "Failed to close FD.", ioe);
        }

        // If the connection fails and pid == 0, the Java-side cleanup was already handled by
        // ServiceCallback.onChildStopped. We still have to call back to native for cleanup there.
        if (mNativeChildProcessLauncherHelper != 0) {
            nativeOnChildProcessStarted(mNativeChildProcessLauncherHelper, getPid());
        }
        mNativeChildProcessLauncherHelper = 0;
    }

    private void onChildProcessDied() {
        assert LauncherThread.runningOnLauncherThread();
        if (getPid() != 0) {
            onConnectionLost(mConnection, getPid());
            sLauncherByPid.remove(getPid());
        }
    }

    public int getPid() {
        assert LauncherThread.runningOnLauncherThread();
        return mConnection == null ? NULL_PROCESS_HANDLE : mConnection.getPid();
    }

    // Called on client (UI or IO) thread.
    @CalledByNative
    private boolean isOomProtected() {
        // mConnection is set on a different thread but does not change once it's been set. So it is
        // safe to test whether it's null from a different thread.
        if (mConnection == null) {
            return false;
        }

        // We consider the process to be child protected if it has a strong or moderate binding and
        // the app is in the foreground.
        return sApplicationInForeground && !mConnection.isWaivedBoundOnlyOrWasWhenDied();
    }

    @CalledByNative
    private void setInForeground(int pid, boolean foreground, boolean boostForPendingViews) {
        assert LauncherThread.runningOnLauncherThread();
        assert mConnection != null;
        assert getPid() == pid;
        getBindingManager().setPriority(pid, foreground, boostForPendingViews);
    }

    @CalledByNative
    static void stop(int pid) {
        assert LauncherThread.runningOnLauncherThread();
        Log.d(TAG, "stopping child connection: pid=%d", pid);
        ChildProcessLauncherHelper launcher = sLauncherByPid.get(pid);
        // Launcher can be null for single process.
        if (launcher != null) {
            launcher.mConnection.stop();
        }
    }

    @CalledByNative
    private static int getNumberOfRendererSlots() {
        assert ThreadUtils.runningOnUiThread();
        if (sSandboxedServicesCountForTesting != -1) {
            return sSandboxedServicesCountForTesting;
        }

        final ChildProcessCreationParams params = ChildProcessCreationParams.getDefault();
        final Context context = ContextUtils.getApplicationContext();
        final String packageName = ChildProcessLauncherHelper.getPackageNameFromCreationParams(
                context, params, true /* inSandbox */);
        try {
            return ChildConnectionAllocator.getNumberOfServices(
                    context, packageName, NUM_SANDBOXED_SERVICES_KEY);
        } catch (RuntimeException e) {
            // Unittest packages do not declare services. Some tests require a realistic number
            // to test child process policies, so pick a high-ish number here.
            return 65535;
        }
    }

    // Can be called on a number of threads, including launcher, and binder.
    private static native void nativeOnChildProcessStarted(
            long nativeChildProcessLauncherHelper, int pid);

    private static boolean sLinkerInitialized;
    private static long sLinkerLoadAddress;
    @VisibleForTesting
    static void initLinker() {
        assert LauncherThread.runningOnLauncherThread();
        if (sLinkerInitialized) return;
        if (Linker.isUsed()) {
            sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress();
            if (sLinkerLoadAddress == 0) {
                Log.i(TAG, "Shared RELRO support disabled!");
            }
        }
        sLinkerInitialized = true;
    }

    private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
        assert LauncherThread.runningOnLauncherThread();
        assert sLinkerInitialized;

        if (sLinkerLoadAddress == 0) return null;

        // Always wait for the shared RELROs in service processes.
        final boolean waitForSharedRelros = true;
        if (Linker.areTestsEnabled()) {
            Linker linker = Linker.getInstance();
            return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros,
                    linker.getTestRunnerClassNameForTesting(),
                    linker.getImplementationForTesting());
        } else {
            return new ChromiumLinkerParams(sLinkerLoadAddress, waitForSharedRelros);
        }
    }

    /**
     * Creates the common bundle to be passed to child processes through the service binding intent.
     * If the service gets recreated by the framework the intent will be reused, so these parameters
     * should be common to all processes of that type.
     *
     * @param commandLine Command line params to be passed to the service.
     * @param linkerParams Linker params to start the service.
     */
    private static Bundle createServiceBundle(boolean bindToCallerCheck) {
        initLinker();
        Bundle bundle = new Bundle();
        bundle.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bindToCallerCheck);
        bundle.putParcelable(ContentChildProcessConstants.EXTRA_LINKER_PARAMS,
                getLinkerParamsForNewConnection());
        return bundle;
    }

    public Bundle createConnectionBundle() {
        Bundle bundle = new Bundle();
        bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, mCommandLine);
        bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, mFilesToBeMapped);
        return bundle;
    }

    // Below are methods that will eventually be moved to a content delegate class.

    private void onBeforeConnectionAllocated(Bundle commonParameters) {
        // TODO(jcivelli): move createServiceBundle in there.
    }

    // Called once a connection has been allocated.
    private void onConnectionBound(ChildProcessConnection connection,
            ChildConnectionAllocator connectionAllocator, Bundle connectionBundle) {
        if (mSandboxed && !connectionAllocator.isFreeConnectionAvailable()) {
            // Proactively releases all the moderate bindings once all the sandboxed services are
            // allocated, which will be very likely to have some of them killed by OOM killer.
            getBindingManager().releaseAllModerateBindings();
        }

        // Popuplate the bundle passed to the service setup call with content specific parameters.
        connectionBundle.putInt(
                ContentChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCount());
        connectionBundle.putLong(
                ContentChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.getMask());
        connectionBundle.putBundle(
                Linker.EXTRA_LINKER_SHARED_RELROS, Linker.getInstance().getSharedRelros());
    }

    private void onConnectionEstablished(ChildProcessConnection connection) {
        if (mSandboxed) {
            getBindingManager().addNewConnection(connection.getPid(), connection);
        }
    }

    // Called when a connection has been disconnected. Only invoked if onConnectionEstablished was
    // called, meaning the connection was already established.
    private void onConnectionLost(ChildProcessConnection connection, int pid) {
        if (mSandboxed) {
            getBindingManager().removeConnection(pid);
        }
    }

    private IBinder getIBinderCallback() {
        return mIBinderCallback;
    }

    // Testing only related methods.
    @VisibleForTesting
    public static ChildProcessLauncherHelper createAndStartForTesting(
            ChildProcessCreationParams creationParams, String[] commandLine,
            FileDescriptorInfo[] filesToBeMapped, boolean sandboxed, IBinder binderCallback,
            boolean doSetupConnection) {
        ChildProcessLauncherHelper launcherHelper =
                new ChildProcessLauncherHelper(0L, creationParams, commandLine, filesToBeMapped,
                        sandboxed, binderCallback, doSetupConnection);
        launcherHelper.start();
        return launcherHelper;
    }

    @VisibleForTesting
    public static ChildProcessLauncherHelper getLauncherForPid(int pid) {
        return sLauncherByPid.get(pid);
    }

    /** @return the count of services set-up and working. */
    @VisibleForTesting
    static int getConnectedServicesCountForTesting() {
        int count = sPrivilegedChildConnectionAllocator == null
                ? 0
                : sPrivilegedChildConnectionAllocator.allocatedConnectionsCountForTesting();
        return count + getConnectedSandboxedServicesCountForTesting(null /* packageName */);
    }

    @VisibleForTesting
    public static int getConnectedSandboxedServicesCountForTesting(String packageName) {
        int count = 0;
        for (ChildConnectionAllocator allocator : sSandboxedChildConnectionAllocatorMap.values()) {
            if (packageName == null || packageName.equals(allocator.getPackageName())) {
                count += allocator.allocatedConnectionsCountForTesting();
            }
        }
        return count;
    }

    @VisibleForTesting
    static boolean hasSandboxedConnectionAllocatorForPackage(String packageName) {
        return sSandboxedChildConnectionAllocatorMap.containsKey(packageName);
    }

    @VisibleForTesting
    ChildProcessConnection getConnection() {
        return mConnection;
    }

    @VisibleForTesting
    public ChildProcessConnection getChildProcessConnection() {
        return mConnection;
    }

    @VisibleForTesting
    public ChildConnectionAllocator getChildConnectionAllocatorForTesting() {
        return mConnectionAllocator;
    }

    @VisibleForTesting
    public static ChildProcessConnection getWarmUpConnectionForTesting() {
        return sSpareSandboxedConnection == null ? null : sSpareSandboxedConnection.getConnection();
    }

    @VisibleForTesting
    public static boolean crashProcessForTesting(int pid) {
        if (sLauncherByPid.get(pid) == null) return false;

        ChildProcessConnection connection = sLauncherByPid.get(pid).mConnection;
        if (connection == null) return false;

        try {
            connection.crashServiceForTesting();
            return true;
        } catch (RemoteException ex) {
            return false;
        }
    }
}
