// Copyright 2014 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.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.BaseSwitches;
import org.chromium.base.ThreadUtils;
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.base.process_launcher.ChildProcessCreationParams;
import org.chromium.base.process_launcher.FileDescriptorInfo;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.test.ChildProcessAllocatorSettings;
import org.chromium.content.browser.test.ContentJUnit4ClassRunner;
import org.chromium.content.browser.test.util.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content_shell_apk.ChildProcessLauncherTestHelperService;
import org.chromium.content_shell_apk.ChildProcessLauncherTestUtils;

import java.util.concurrent.Callable;

/**
 * Instrumentation tests for ChildProcessLauncher.
 */
@RunWith(ContentJUnit4ClassRunner.class)
public class ChildProcessLauncherTest {
    // Pseudo command line arguments to instruct the child process to wait until being killed.
    // Allowing the process to continue would lead to a crash when attempting to initialize IPC
    // channels that are not being set up in this test.
    private static final String[] sProcessWaitArguments = {
        "_", "--" + BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER };
    private static final String EXTERNAL_APK_PACKAGE_NAME = "org.chromium.external.apk";
    private static final String DEFAULT_SANDBOXED_PROCESS_SERVICE =
            "org.chromium.content.app.SandboxedProcessService";

    private static final int DONT_BLOCK = 0;
    private static final int BLOCK_UNTIL_CONNECTED = 1;
    private static final int BLOCK_UNTIL_SETUP = 2;

    @Before
    public void setUp() throws Exception {
        LibraryLoader.get(LibraryProcessType.PROCESS_CHILD).ensureInitialized();
        ChildProcessLauncherTestUtils.runOnLauncherThreadBlocking(new Runnable() {
            @Override
            public void run() {
                ChildProcessLauncherHelper.initLinker();
            }
        });
    }

    /**
     *  Tests cleanup for a connection that fails to connect in the first place.
     */
    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    @ChildProcessAllocatorSettings(sandboxedServiceCount = 4)
    public void testServiceFailedToBind() {
        Assert.assertEquals(0, getConnectedSandboxedServicesCount());

        // Try to allocate a connection to service class in incorrect package. We can do that by
        // using the instrumentation context (getContext()) instead of the app context
        // (getTargetContext()).
        Context context = InstrumentationRegistry.getInstrumentation().getContext();
        startSandboxedChildProcess(
                context.getPackageName(), DONT_BLOCK, true /* doSetupConnection */);

        // Verify that the connection is not considered as allocated.
        waitForConnectedSandboxedServicesCount(0);
    }

    /**
     * Tests cleanup for a connection that terminates before setup.
     */
    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testServiceCrashedBeforeSetup() throws RemoteException {
        Assert.assertEquals(0, getConnectedSandboxedServicesCount());

        // Start and connect to a new service.
        ChildProcessLauncherHelper launcher = startSandboxedChildProcess(
                null /* packageName */, BLOCK_UNTIL_CONNECTED, false /* doSetupConnection */);

        // Verify that the service is bound but not yet set up.
        Assert.assertEquals(1, getConnectedSandboxedServicesCount());
        ChildProcessConnection connection = retrieveConnection(launcher);
        Assert.assertNotNull(connection);
        Assert.assertTrue(connection.isConnected());
        Assert.assertEquals(0, ChildProcessLauncherTestUtils.getConnectionPid(connection));

        // Crash the service.
        connection.crashServiceForTesting();

        // Verify that the connection gets cleaned-up.
        waitForConnectedSandboxedServicesCount(0);
    }

    /**
     * Tests cleanup for a connection that terminates after setup.
     */
    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testServiceCrashedAfterSetup() throws RemoteException {
        Assert.assertEquals(0, getConnectedSandboxedServicesCount());

        // Start and connect to a new service.
        ChildProcessLauncherHelper launcher = startSandboxedChildProcess(
                null /* packageName */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
        Assert.assertEquals(1, getConnectedSandboxedServicesCount());

        int pid = getPid(launcher);
        Assert.assertNotEquals(0, pid);

        // Crash the service.
        ChildProcessConnection connection = retrieveConnection(launcher);
        connection.crashServiceForTesting();

        // Verify that the connection gets cleaned-up.
        waitForConnectedSandboxedServicesCount(0);

        // Verify that the connection pid remains set after termination.
        Assert.assertTrue(ChildProcessLauncherTestUtils.getConnectionPid(connection) != 0);
        // And that the launcher is cleared.
        Assert.assertNull(ChildProcessLauncherHelper.getLauncherForPid(pid));
    }

    /**
     * Tests that connection requests get queued when no slot is availabe and created once a slot
     * frees up .
     */
    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    @ChildProcessAllocatorSettings(sandboxedServiceCount = 1)
    public void testPendingSpawnQueue() throws RemoteException {
        Assert.assertEquals(0, getConnectedSandboxedServicesCount());

        ChildProcessLauncherHelper launcher1 = startSandboxedChildProcess(
                null /* packageName */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
        Assert.assertEquals(1, getConnectedSandboxedServicesCount());
        Assert.assertNotNull(ChildProcessLauncherTestUtils.getConnection(launcher1));

        ChildProcessLauncherHelper launcher2 = startSandboxedChildProcess(
                null /* packageName */, DONT_BLOCK, true /* doSetupConnection */);
        Assert.assertEquals(1, getConnectedSandboxedServicesCount());
        Assert.assertNull(ChildProcessLauncherTestUtils.getConnection(launcher2));

        final ChildProcessConnection connection1 =
                ChildProcessLauncherTestUtils.getConnection(launcher1);
        connection1.crashServiceForTesting();

        // The previous service crashing should have freed a connection that should be used for the
        // pending process.
        blockUntilConnected(launcher2);
    }

    /**
     * Tests that external APKs and regular use different ChildConnectionAllocators.
     */
    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    @ChildProcessAllocatorSettings(
            sandboxedServiceCount = 4, sandboxedServiceName = DEFAULT_SANDBOXED_PROCESS_SERVICE)
    public void testAllocatorForPackage() {
        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();

        ChildConnectionAllocator connectionAllocator = getChildConnectionAllocator(
                appContext, appContext.getPackageName(), true /* sandboxed */);
        ChildConnectionAllocator externalConnectionAllocator = getChildConnectionAllocator(
                appContext, EXTERNAL_APK_PACKAGE_NAME, true /* sandboxed */);
        Assert.assertNotEquals(connectionAllocator, externalConnectionAllocator);
    }

    /**
     * Tests binding to the same sandboxed service process from multiple processes in the
     * same package. This uses the ChildProcessLauncherTestHelperService declared in
     * ContentShell.apk as a separate android:process to bind the first (slot 0) service. The
     * instrumentation test then tries to bind the same slot, which fails, so the
     * ChildProcessLauncher retries on a new connection.
     */
    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testBindServiceFromMultipleProcesses() throws RemoteException {
        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();

        // Start the Helper service.
        class HelperConnection implements ServiceConnection {
            Messenger mMessenger = null;

            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                mMessenger = new Messenger(service);
            }

            @Override
            public void onServiceDisconnected(ComponentName name) {}
        }
        final HelperConnection serviceConnection = new HelperConnection();

        Intent intent = new Intent();
        intent.setComponent(new ComponentName(context.getPackageName(),
                context.getPackageName() + ".ChildProcessLauncherTestHelperService"));
        Assert.assertTrue(context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE));

        // Wait for the Helper service to connect.
        CriteriaHelper.pollInstrumentationThread(
                new Criteria("Failed to get helper service Messenger") {
                    @Override
                    public boolean isSatisfied() {
                        return serviceConnection.mMessenger != null;
                    }
                });

        Assert.assertNotNull(serviceConnection.mMessenger);

        class ReplyHandler implements Handler.Callback {
            Message mMessage;

            @Override
            public boolean handleMessage(Message msg) {
                // Copy the message so its contents outlive this Binder transaction.
                mMessage = Message.obtain();
                mMessage.copyFrom(msg);
                return true;
            }
        }
        final ReplyHandler replyHandler = new ReplyHandler();

        // Send a message to the Helper and wait for the reply. This will cause the slot 0
        // sandboxed service connection to be bound by a different PID (i.e., not this process).
        Message msg = Message.obtain(null, ChildProcessLauncherTestHelperService.MSG_BIND_SERVICE);
        msg.replyTo = new Messenger(new Handler(Looper.getMainLooper(), replyHandler));
        serviceConnection.mMessenger.send(msg);

        CriteriaHelper.pollInstrumentationThread(
                new Criteria("Failed waiting for helper service reply") {
                    @Override
                    public boolean isSatisfied() {
                        return replyHandler.mMessage != null;
                    }
                });

        // Verify that the Helper was able to launch the sandboxed service.
        Assert.assertNotNull(replyHandler.mMessage);
        Assert.assertEquals(ChildProcessLauncherTestHelperService.MSG_BIND_SERVICE_REPLY,
                replyHandler.mMessage.what);
        Assert.assertEquals(
                "Connection slot from helper service is not 0", 0, replyHandler.mMessage.arg2);

        final int helperConnectionPid = replyHandler.mMessage.arg1;
        Assert.assertTrue(helperConnectionPid > 0);

        // Launch a service from this process. Since slot 0 is already bound by the Helper, it
        // will fail to start and the ChildProcessLauncher will retry and use the slot 1.
        ChildProcessCreationParams creationParams = new ChildProcessCreationParams(
                context.getPackageName(), false /* isExternalService */,
                LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */);
        ChildProcessLauncherHelper launcher = startSandboxedChildProcessWithCreationParams(
                creationParams, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);

        final ChildProcessConnection retryConnection =
                ChildProcessLauncherTestUtils.getConnection(launcher);
        Assert.assertEquals(
                1, ChildProcessLauncherTestUtils.getConnectionServiceNumber(retryConnection));

        ChildConnectionAllocator connectionAllocator =
                launcher.getChildConnectionAllocatorForTesting();

        // Check that only two connections are created.
        for (int i = 0; i < connectionAllocator.getNumberOfServices(); ++i) {
            ChildProcessConnection sandboxedConn =
                    connectionAllocator.getChildProcessConnectionAtSlotForTesting(i);
            if (i <= 1) {
                Assert.assertNotNull(sandboxedConn);
                Assert.assertNotNull(
                        ChildProcessLauncherTestUtils.getConnectionService(sandboxedConn));
            } else {
                Assert.assertNull(sandboxedConn);
            }
        }

        Assert.assertEquals(
                connectionAllocator.getChildProcessConnectionAtSlotForTesting(1), retryConnection);

        ChildProcessConnection failedConnection =
                connectionAllocator.getChildProcessConnectionAtSlotForTesting(0);
        Assert.assertEquals(0, ChildProcessLauncherTestUtils.getConnectionPid(failedConnection));
        Assert.assertFalse(ChildProcessLauncherTestUtils.getConnectionService(failedConnection)
                                   .bindToCaller());

        CriteriaHelper.pollInstrumentationThread(
                new Criteria("Failed waiting retry connection to get pid") {
                    @Override
                    public boolean isSatisfied() {
                        return ChildProcessLauncherTestUtils.getConnectionPid(retryConnection) > 0;
                    }
                });
        Assert.assertTrue(ChildProcessLauncherTestUtils.getConnectionPid(retryConnection)
                != helperConnectionPid);
        Assert.assertTrue(
                ChildProcessLauncherTestUtils.getConnectionService(retryConnection).bindToCaller());
    }

    private static void warmUpOnUiThreadBlocking(final Context context) {
        ThreadUtils.runOnUiThreadBlocking(new Runnable() {
            @Override
            public void run() {
                ChildProcessLauncherHelper.warmUp(context);
            }
        });
        ChildProcessConnection connection = getWarmUpConnection();
        Assert.assertNotNull(connection);
        blockUntilConnected(connection);
    }

    private void testWarmUpWithCreationParams(ChildProcessCreationParams creationParams) {
        if (creationParams != null) {
            ChildProcessCreationParams.registerDefault(creationParams);
        }

        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        warmUpOnUiThreadBlocking(context);

        Assert.assertEquals(1, getConnectedSandboxedServicesCount());

        ChildProcessLauncherHelper launcherHelper = startSandboxedChildProcessWithCreationParams(
                creationParams, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);

        // The warm-up connection was used, so no new process should have been created.
        Assert.assertEquals(1, getConnectedSandboxedServicesCount());

        int pid = getPid(launcherHelper);
        Assert.assertNotEquals(0, pid);

        stopProcess(launcherHelper);

        waitForConnectedSandboxedServicesCount(0);
        Assert.assertNull(ChildProcessLauncherHelper.getLauncherForPid(pid));
    }

    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testWarmUp() {
        // Use the default creation parameters.
        testWarmUpWithCreationParams(null /* creationParams */);
    }

    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testWarmUpWithBindToCaller() {
        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        ChildProcessCreationParams creationParams = new ChildProcessCreationParams(
                context.getPackageName(), false /* isExternalService */,
                LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */);
        testWarmUpWithCreationParams(creationParams);
    }

    // Tests that the warm-up connection is freed from its allocator if it crashes.
    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testWarmUpProcessCrashBeforeUse() throws RemoteException {
        Assert.assertEquals(0, getConnectedSandboxedServicesCount());

        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        warmUpOnUiThreadBlocking(context);

        Assert.assertEquals(1, getConnectedSandboxedServicesCount());

        // Crash the warm-up connection before it gets used.
        ChildProcessConnection connection = getWarmUpConnection();
        Assert.assertNotNull(connection);
        connection.crashServiceForTesting();

        // It should get cleaned-up.
        waitForConnectedSandboxedServicesCount(0);

        // And subsequent process launches should work.
        ChildProcessLauncherHelper launcher = startSandboxedChildProcess(
                null /* packageName */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
        Assert.assertEquals(1, getConnectedSandboxedServicesCount());
        Assert.assertNotNull(ChildProcessLauncherTestUtils.getConnection(launcher));
    }

    // Tests that the warm-up connection is freed from its allocator if it crashes after being used.
    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testWarmUpProcessCrashAfterUse() throws RemoteException {
        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        warmUpOnUiThreadBlocking(context);

        Assert.assertEquals(1, getConnectedSandboxedServicesCount());

        ChildProcessLauncherHelper launcherHelper = startSandboxedChildProcessWithCreationParams(
                null /* creationParams */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);

        // The warm-up connection was used, so no new process should have been created.
        Assert.assertEquals(1, getConnectedSandboxedServicesCount());

        int pid = getPid(launcherHelper);
        Assert.assertNotEquals(0, pid);

        ChildProcessConnection connection = retrieveConnection(launcherHelper);
        connection.crashServiceForTesting();

        waitForConnectedSandboxedServicesCount(0);
        Assert.assertNull(ChildProcessLauncherHelper.getLauncherForPid(pid));
    }

    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testSandboxedAllocatorFreed() {
        final String packageName =
                InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName();

        ChildProcessLauncherHelper launcher = startSandboxedChildProcess(
                null /* packageName */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);

        Assert.assertTrue(hasSandboxedConnectionAllocatorForPackage(packageName));

        stopProcess(launcher);

        // Poll until allocator is removed. Need to poll here because actually freeing a connection
        // from allocator is a posted task, rather than a direct call from stop.
        CriteriaHelper.pollInstrumentationThread(
                new Criteria("The connection allocator was not removed.") {
                    @Override
                    public boolean isSatisfied() {
                        return !hasSandboxedConnectionAllocatorForPackage(packageName);
                    }
                });
    }

    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testCustomCreationParamDoesNotReuseWarmupConnection() {
        // Since warmUp only uses default params.
        final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        ChildProcessCreationParams defaultCreationParams =
                getDefaultChildProcessCreationParams(context.getPackageName());
        ChildProcessCreationParams otherCreationParams =
                getDefaultChildProcessCreationParams(context.getPackageName());
        ChildProcessCreationParams.registerDefault(defaultCreationParams);

        warmUpOnUiThreadBlocking(context);
        Assert.assertEquals(1, getConnectedSandboxedServicesCount());

        // First create a connnection with different creation params then the default. It should not
        // use the warm-up connection which uses the default creation params (check uses object
        // identity, having the params match exactly is fine).
        startSandboxedChildProcessWithCreationParams(
                otherCreationParams, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
        Assert.assertEquals(2, getConnectedSandboxedServicesCount());
        Assert.assertNotNull(getWarmUpConnection());

        // Then start a process with the default creation params, the warmup-connection should be
        // used.
        startSandboxedChildProcessWithCreationParams(
                defaultCreationParams, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
        Assert.assertEquals(2, getConnectedSandboxedServicesCount());
        Assert.assertNull(getWarmUpConnection());
    }

    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testUseStrongBindingConnection() {
        // Since warmUp only uses default params.
        Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
        ChildProcessCreationParams creationParams = new ChildProcessCreationParams(
                context.getPackageName(), false /* isExternalService */,
                LibraryProcessType.PROCESS_CHILD, true /* bindToCallerCheck */);

        for (final boolean useStrongBinding : new boolean[] {true, false}) {
            ChildProcessLauncherHelper launcher = ChildProcessLauncherTestUtils.startForTesting(
                    false /* sandboxed */, useStrongBinding, sProcessWaitArguments,
                    new FileDescriptorInfo[0], creationParams, true /* doSetupConnection */);
            final ChildProcessConnection connection =
                    ChildProcessLauncherTestUtils.getConnection(launcher);
            Assert.assertNotNull(connection);
            ChildProcessLauncherTestUtils.runOnLauncherThreadBlocking(new Runnable() {
                @Override
                public void run() {
                    Assert.assertEquals(useStrongBinding, connection.isStrongBindingBound());
                }
            });
        }
    }

    @Test
    @MediumTest
    @Feature({"ProcessManagement"})
    public void testLauncherCleanup() throws RemoteException {
        ChildProcessLauncherHelper launcher = startSandboxedChildProcess(
                null /* packageName */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
        int pid = getPid(launcher);
        Assert.assertNotEquals(0, pid);
        Assert.assertNotNull(ChildProcessLauncherHelper.getLauncherForPid(pid));

        // Stop the process explicitly, the launcher should get cleared.
        stopProcess(launcher);
        waitForConnectedSandboxedServicesCount(0);
        Assert.assertNull(ChildProcessLauncherHelper.getLauncherForPid(pid));

        launcher = startSandboxedChildProcess(
                null /* packageName */, BLOCK_UNTIL_SETUP, true /* doSetupConnection */);
        pid = getPid(launcher);
        Assert.assertNotEquals(0, pid);
        Assert.assertNotNull(ChildProcessLauncherHelper.getLauncherForPid(pid));

        // This time crash the connection, the launcher should also get cleared.
        ChildProcessConnection connection = retrieveConnection(launcher);
        connection.crashServiceForTesting();
        waitForConnectedSandboxedServicesCount(0);
        Assert.assertNull(ChildProcessLauncherHelper.getLauncherForPid(pid));
    }

    private static ChildProcessLauncherHelper startSandboxedChildProcess(
            final String packageName, int blockingPolicy, final boolean doSetupConnection) {
        ChildProcessCreationParams creationParams =
                packageName == null ? null : getDefaultChildProcessCreationParams(packageName);
        return startSandboxedChildProcessWithCreationParams(
                creationParams, blockingPolicy, doSetupConnection);
    }

    private static ChildProcessLauncherHelper startSandboxedChildProcessWithCreationParams(
            final ChildProcessCreationParams creationParams, int blockingPolicy,
            final boolean doSetupConnection) {
        assert doSetupConnection || blockingPolicy != BLOCK_UNTIL_SETUP;
        ChildProcessLauncherHelper launcher =
                ChildProcessLauncherTestUtils.runOnLauncherAndGetResult(
                        new Callable<ChildProcessLauncherHelper>() {
                            @Override
                            public ChildProcessLauncherHelper call() {
                                return ChildProcessLauncherHelper.createAndStartForTesting(
                                        creationParams, sProcessWaitArguments,
                                        new FileDescriptorInfo[0], false /* useStrongBinding */,
                                        true /* sandboxed */, null /* binderCallback */,
                                        doSetupConnection);
                            }
                        });
        if (blockingPolicy != DONT_BLOCK) {
            assert blockingPolicy == BLOCK_UNTIL_CONNECTED || blockingPolicy == BLOCK_UNTIL_SETUP;
            blockUntilConnected(launcher);
            if (blockingPolicy == BLOCK_UNTIL_SETUP) {
                blockUntilSetup(launcher);
            }
        }
        return launcher;
    }

    private static void blockUntilConnected(final ChildProcessLauncherHelper launcher) {
        CriteriaHelper.pollInstrumentationThread(
                new Criteria("The connection wasn't established.") {
                    @Override
                    public boolean isSatisfied() {
                        return launcher.getConnection() != null
                                && launcher.getConnection().isConnected();
                    }
                });
    }

    private static void blockUntilConnected(final ChildProcessConnection connection) {
        CriteriaHelper.pollInstrumentationThread(
                new Criteria("The connection wasn't established.") {
                    @Override
                    public boolean isSatisfied() {
                        return connection.isConnected();
                    }
                });
    }

    private static void blockUntilSetup(final ChildProcessLauncherHelper launcher) {
        CriteriaHelper.pollInstrumentationThread(
                new Criteria("The connection wasn't established.") {
                    @Override
                    public boolean isSatisfied() {
                        return getPid(launcher) != 0;
                    }
                });
    }

    private static ChildConnectionAllocator getChildConnectionAllocator(
            final Context context, final String packageName, final boolean sandboxed) {
        return ChildProcessLauncherTestUtils.runOnLauncherAndGetResult(
                new Callable<ChildConnectionAllocator>() {
                    @Override
                    public ChildConnectionAllocator call() {
                        return ChildProcessLauncherHelper.getConnectionAllocator(context,
                                getDefaultChildProcessCreationParams(packageName), sandboxed);
                    }
                });
    }

    // Returns the number of sandboxed connection currently connected,
    private static int getConnectedSandboxedServicesCount() {
        return getConnectedSandboxedServicesCountForPackage(null /* packageName */);
    }

    // Returns the number of sandboxed connection matching the specificed package name that are
    // connected,
    private static int getConnectedSandboxedServicesCountForPackage(final String packageName) {
        return ChildProcessLauncherTestUtils.runOnLauncherAndGetResult(
                new Callable<Integer>() {
                    @Override
                    public Integer call() {
                        return ChildProcessLauncherHelper
                                .getConnectedSandboxedServicesCountForTesting(packageName);
                    }
                });
    }

    // Blocks until the number of sandboxed connections reaches targetCount.
    private static void waitForConnectedSandboxedServicesCount(int targetCount) {
        CriteriaHelper.pollInstrumentationThread(
                Criteria.equals(targetCount, new Callable<Integer>() {
                    @Override
                    public Integer call() {
                        return getConnectedSandboxedServicesCountForPackage(null /* packageName */);
                    }
                }));
    }

    private static ChildProcessCreationParams getDefaultChildProcessCreationParams(
            String packageName) {
        return packageName == null
                ? null
                : new ChildProcessCreationParams(packageName, false /* isExternalService */,
                          LibraryProcessType.PROCESS_CHILD, false /* bindToCallerCheck */);
    }

    private static boolean hasSandboxedConnectionAllocatorForPackage(final String packageName) {
        return ChildProcessLauncherTestUtils.runOnLauncherAndGetResult(new Callable<Boolean>() {
            @Override
            public Boolean call() {
                return ChildProcessLauncherHelper.hasSandboxedConnectionAllocatorForPackage(
                        packageName);
            }
        });
    }

    private static ChildProcessConnection retrieveConnection(
            final ChildProcessLauncherHelper launcherHelper) {
        CriteriaHelper.pollInstrumentationThread(
                new Criteria("Failed waiting for child process to connect") {
                    @Override
                    public boolean isSatisfied() {
                        return ChildProcessLauncherTestUtils.getConnection(launcherHelper) != null;
                    }
                });

        return ChildProcessLauncherTestUtils.getConnection(launcherHelper);
    }

    private static void stopProcess(ChildProcessLauncherHelper launcherHelper) {
        final ChildProcessConnection connection = retrieveConnection(launcherHelper);
        ChildProcessLauncherTestUtils.runOnLauncherThreadBlocking(new Runnable() {
            @Override
            public void run() {
                ChildProcessLauncherHelper.stop(connection.getPid());
            }
        });
    }

    private static int getPid(final ChildProcessLauncherHelper launcherHelper) {
        return ChildProcessLauncherTestUtils.runOnLauncherAndGetResult(new Callable<Integer>() {
            @Override
            public Integer call() {
                return launcherHelper.getPid();
            }
        });
    }

    private static ChildProcessConnection getWarmUpConnection() {
        return ChildProcessLauncherTestUtils.runOnLauncherAndGetResult(
                new Callable<ChildProcessConnection>() {
                    @Override
                    public ChildProcessConnection call() {
                        return ChildProcessLauncherHelper.getWarmUpConnectionForTesting();
                    }
                });
    }
}
