1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)package org.chromium.content.browser;
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.content.Context;
8c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochimport android.graphics.SurfaceTexture;
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)import android.os.RemoteException;
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.util.Log;
11c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochimport android.util.Pair;
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.view.Surface;
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.base.CalledByNative;
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.base.JNINamespace;
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.base.ThreadUtils;
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuimport org.chromium.base.TraceEvent;
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.base.VisibleForTesting;
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import org.chromium.base.library_loader.Linker;
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.content.app.ChildProcessService;
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import org.chromium.content.app.ChromiumLinkerParams;
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.content.app.PrivilegedProcessService;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.content.app.SandboxedProcessService;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import org.chromium.content.common.IChildProcessCallback;
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)import org.chromium.content.common.SurfaceWrapper;
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import java.util.ArrayList;
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import java.util.Map;
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import java.util.concurrent.ConcurrentHashMap;
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/**
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * This class provides the method to start/stop ChildProcess called by native.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)@JNINamespace("content")
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)public class ChildProcessLauncher {
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private static final String TAG = "ChildProcessLauncher";
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    static final int CALLBACK_FOR_UNKNOWN_PROCESS = 0;
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    static final int CALLBACK_FOR_GPU_PROCESS = 1;
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    static final int CALLBACK_FOR_RENDERER_PROCESS = 2;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final String SWITCH_PROCESS_TYPE = "type";
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final String SWITCH_PPAPI_BROKER_PROCESS = "ppapi-broker";
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final String SWITCH_RENDERER_PROCESS = "renderer";
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final String SWITCH_GPU_PROCESS = "gpu-process";
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The upper limit on the number of simultaneous sandboxed and privileged child service process
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // instances supported. Each limit must not exceed total number of SandboxedProcessServiceX
49bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // classes and PrivilegedProcessServiceX classes declared in this package and defined as
50bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // services in the embedding application's manifest file.
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // (See {@link ChildProcessService} for more details on defining the services.)
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    /* package */ static final int MAX_REGISTERED_SANDBOXED_SERVICES = 20;
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* package */ static final int MAX_REGISTERED_PRIVILEGED_SERVICES = 3;
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static class ChildConnectionAllocator {
56bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // Connections to services. Indices of the array correspond to the service numbers.
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        private final ChildProcessConnection[] mChildProcessConnections;
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
59bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // The list of free (not bound) service indices. When looking for a free service, the first
60bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // index in that list should be used. When a service is unbound, its index is added to the
61bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // end of the list. This is so that we avoid immediately reusing the freed service (see
62bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // http://crbug.com/164069): the framework might keep a service process alive when it's been
63bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // unbound for a short time. If a new connection to the same service is bound at that point,
64bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // the process is reused and bad things happen (mostly static variables are set when we
65bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // don't expect them to).
66bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch        // SHOULD BE ACCESSED WITH mConnectionLock.
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        private final ArrayList<Integer> mFreeConnectionIndices;
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        private final Object mConnectionLock = new Object();
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        private Class<? extends ChildProcessService> mChildClass;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        private final boolean mInSandbox;
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public ChildConnectionAllocator(boolean inSandbox) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            int numChildServices = inSandbox ?
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    MAX_REGISTERED_SANDBOXED_SERVICES : MAX_REGISTERED_PRIVILEGED_SERVICES;
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            mChildProcessConnections = new ChildProcessConnectionImpl[numChildServices];
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mFreeConnectionIndices = new ArrayList<Integer>(numChildServices);
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            for (int i = 0; i < numChildServices; i++) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                mFreeConnectionIndices.add(i);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            setServiceClass(inSandbox ?
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    SandboxedProcessService.class : PrivilegedProcessService.class);
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mInSandbox = inSandbox;
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void setServiceClass(Class<? extends ChildProcessService> childClass) {
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mChildClass = childClass;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public ChildProcessConnection allocate(
918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                Context context, ChildProcessConnection.DeathCallback deathCallback,
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                ChromiumLinkerParams chromiumLinkerParams) {
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            synchronized (mConnectionLock) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (mFreeConnectionIndices.isEmpty()) {
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    Log.e(TAG, "Ran out of services to allocate.");
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    assert false;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    return null;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                int slot = mFreeConnectionIndices.remove(0);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                assert mChildProcessConnections[slot] == null;
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                mChildProcessConnections[slot] = new ChildProcessConnectionImpl(context, slot,
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        mInSandbox, deathCallback, mChildClass, chromiumLinkerParams);
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                Log.d(TAG, "Allocator allocated a connection, sandbox: " + mInSandbox +
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                        ", slot: " + slot);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return mChildProcessConnections[slot];
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        public void free(ChildProcessConnection connection) {
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            synchronized (mConnectionLock) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                int slot = connection.getServiceNumber();
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (mChildProcessConnections[slot] != connection) {
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    int occupier = mChildProcessConnections[slot] == null ?
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            -1 : mChildProcessConnections[slot].getServiceNumber();
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    Log.e(TAG, "Unable to find connection to free in slot: " + slot +
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            " already occupied by service: " + occupier);
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    assert false;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                } else {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    mChildProcessConnections[slot] = null;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    assert !mFreeConnectionIndices.contains(slot);
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    mFreeConnectionIndices.add(slot);
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                    Log.d(TAG, "Allocator freed a connection, sandbox: " + mInSandbox +
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                            ", slot: " + slot);
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        /** @return the count of connections managed by the allocator */
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        @VisibleForTesting
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        int allocatedConnectionsCountForTesting() {
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            return mChildProcessConnections.length - mFreeConnectionIndices.size();
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        }
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Service class for child process. As the default value it uses SandboxedProcessService0 and
136bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    // PrivilegedProcessService0.
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    private static final ChildConnectionAllocator sSandboxedChildConnectionAllocator =
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new ChildConnectionAllocator(true);
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    private static final ChildConnectionAllocator sPrivilegedChildConnectionAllocator =
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new ChildConnectionAllocator(false);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    private static boolean sConnectionAllocated = false;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /**
145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * Sets service class for sandboxed service and privileged service.
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     */
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public static void setChildProcessClass(
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Class<? extends SandboxedProcessService> sandboxedServiceClass,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Class<? extends PrivilegedProcessService> privilegedServiceClass) {
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // We should guarantee this is called before allocating connection.
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        assert !sConnectionAllocated;
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        sSandboxedChildConnectionAllocator.setServiceClass(sandboxedServiceClass);
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        sPrivilegedChildConnectionAllocator.setServiceClass(privilegedServiceClass);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static ChildConnectionAllocator getConnectionAllocator(boolean inSandbox) {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return inSandbox ?
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                sSandboxedChildConnectionAllocator : sPrivilegedChildConnectionAllocator;
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static ChildProcessConnection allocateConnection(Context context,
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            boolean inSandbox, ChromiumLinkerParams chromiumLinkerParams) {
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ChildProcessConnection.DeathCallback deathCallback =
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new ChildProcessConnection.DeathCallback() {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                @Override
1665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                public void onChildProcessDied(ChildProcessConnection connection) {
1675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    if (connection.getPid() != 0) {
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        stop(connection.getPid());
1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    } else {
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        freeConnection(connection);
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                    }
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            };
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        sConnectionAllocated = true;
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return getConnectionAllocator(inSandbox).allocate(context, deathCallback,
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                chromiumLinkerParams);
1778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
1788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static boolean sLinkerInitialized = false;
1808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    private static long sLinkerLoadAddress = 0;
1818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    private static ChromiumLinkerParams getLinkerParamsForNewConnection() {
1838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (!sLinkerInitialized) {
1848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            if (Linker.isUsed()) {
1858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                sLinkerLoadAddress = Linker.getBaseLoadAddress();
1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                if (sLinkerLoadAddress == 0) {
1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                    Log.i(TAG, "Shared RELRO support disabled!");
1888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                }
1898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            }
1908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            sLinkerInitialized = true;
1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (sLinkerLoadAddress == 0)
1948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            return null;
1958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Always wait for the shared RELROs in service processes.
1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        final boolean waitForSharedRelros = true;
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return new ChromiumLinkerParams(sLinkerLoadAddress,
1998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                waitForSharedRelros,
2008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                Linker.getTestRunnerClassName());
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static ChildProcessConnection allocateBoundConnection(Context context,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            String[] commandLine, boolean inSandbox) {
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnection();
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ChildProcessConnection connection =
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                allocateConnection(context, inSandbox, chromiumLinkerParams);
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (connection != null) {
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            connection.start(commandLine);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return connection;
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static void freeConnection(ChildProcessConnection connection) {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        getConnectionAllocator(connection.isInSandbox()).free(connection);
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
21858e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch    // Represents an invalid process handle; same as base/process/process.h kNullProcessHandle.
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static final int NULL_PROCESS_HANDLE = 0;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Map from pid to ChildService connection.
222ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    private static Map<Integer, ChildProcessConnection> sServiceMap =
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new ConcurrentHashMap<Integer, ChildProcessConnection>();
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // A pre-allocated and pre-bound connection ready for connection setup, or null.
226ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    private static ChildProcessConnection sSpareSandboxedConnection = null;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Manages oom bindings used to bind chind services.
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    private static BindingManager sBindingManager = BindingManagerImpl.createBindingManager();
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
231c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Map from surface id to Surface.
232c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    private static Map<Integer, Surface> sViewSurfaceMap =
233c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            new ConcurrentHashMap<Integer, Surface>();
234c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
235c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // Map from surface texture id to Surface.
236c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    private static Map<Pair<Integer, Integer>, Surface> sSurfaceTextureSurfaceMap =
237c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            new ConcurrentHashMap<Pair<Integer, Integer>, Surface>();
238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    @VisibleForTesting
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    public static void setBindingManagerForTesting(BindingManager manager) {
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        sBindingManager = manager;
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
244a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    /** @return true iff the child process is protected from out-of-memory killing */
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    @CalledByNative
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private static boolean isOomProtected(int pid) {
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return sBindingManager.isOomProtected(pid);
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    @CalledByNative
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    private static void registerViewSurface(int surfaceId, Surface surface) {
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        sViewSurfaceMap.put(surfaceId, surface);
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    @CalledByNative
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    private static void unregisterViewSurface(int surfaceId) {
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        sViewSurfaceMap.remove(surfaceId);
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    @CalledByNative
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    private static void registerSurfaceTexture(
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch            int surfaceTextureId, int childProcessId, SurfaceTexture surfaceTexture) {
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        Pair<Integer, Integer> key = new Pair<Integer, Integer>(surfaceTextureId, childProcessId);
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        sSurfaceTextureSurfaceMap.put(key, new Surface(surfaceTexture));
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    @CalledByNative
268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    private static void unregisterSurfaceTexture(int surfaceTextureId, int childProcessId) {
269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        Pair<Integer, Integer> key = new Pair<Integer, Integer>(surfaceTextureId, childProcessId);
270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch        sSurfaceTextureSurfaceMap.remove(key);
271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    }
272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /**
274a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch     * Sets the visibility of the child process when it changes or when it is determined for the
275a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch     * first time.
276a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch     */
277a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    @CalledByNative
278a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    public static void setInForeground(int pid, boolean inForeground) {
279a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        sBindingManager.setInForeground(pid, inForeground);
280a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
281a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
282a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    /**
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * Called when the embedding application is sent to background.
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     */
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    public static void onSentToBackground() {
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sBindingManager.onSentToBackground();
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    /**
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * Called when the embedding application is brought to foreground.
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     */
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    public static void onBroughtToForeground() {
293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        sBindingManager.onBroughtToForeground();
294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
297bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch     * Should be called early in startup so the work needed to spawn the child process can be done
298bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch     * in parallel to other startup work. Must not be called on the UI thread. Spare connection is
299bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch     * created in sandboxed child process.
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param context the application context used for the connection.
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    public static void warmUp(Context context) {
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        synchronized (ChildProcessLauncher.class) {
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            assert !ThreadUtils.runningOnUiThread();
305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            if (sSpareSandboxedConnection == null) {
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                sSpareSandboxedConnection = allocateBoundConnection(context, null, true);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static String getSwitchValue(final String[] commandLine, String switchKey) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (commandLine == null || switchKey == null) {
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return null;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // This format should be matched with the one defined in command_line.h.
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        final String switchKeyPrefix = "--" + switchKey + "=";
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (String command : commandLine) {
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (command != null && command.startsWith(switchKeyPrefix)) {
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return command.substring(switchKeyPrefix.length());
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return null;
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
326bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch     * Spawns and connects to a child process. May be called on any thread. It will not block, but
327bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch     * will instead callback to {@link #nativeOnChildProcessStarted} when the connection is
328bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch     * established. Note this callback will not necessarily be from the same thread (currently it
329bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch     * always comes from the main thread).
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param context Context used to obtain the application context.
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param commandLine The child process command line argv.
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * @param fileIds The ID that should be used when mapping files in the created process.
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * @param fileFds The file descriptors that should be mapped in the created process.
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     * @param fileAutoClose Whether the file descriptors should be closed once they were passed to
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * the created process.
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param clientContext Arbitrary parameter used by the client to distinguish this connection.
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @CalledByNative
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static void start(
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            Context context,
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            final String[] commandLine,
3434ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch            int childProcessId,
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            int[] fileIds,
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            int[] fileFds,
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            boolean[] fileAutoClose,
3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            long clientContext) {
3485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        TraceEvent.begin();
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        assert fileIds.length == fileFds.length && fileFds.length == fileAutoClose.length;
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FileDescriptorInfo[] filesToBeMapped = new FileDescriptorInfo[fileFds.length];
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        for (int i = 0; i < fileFds.length; i++) {
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            filesToBeMapped[i] =
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    new FileDescriptorInfo(fileIds[i], fileFds[i], fileAutoClose[i]);
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        assert clientContext != 0;
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS;
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        boolean inSandbox = true;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        String processType = getSwitchValue(commandLine, SWITCH_PROCESS_TYPE);
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (SWITCH_RENDERER_PROCESS.equals(processType)) {
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            callbackType = CALLBACK_FOR_RENDERER_PROCESS;
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else if (SWITCH_GPU_PROCESS.equals(processType)) {
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            callbackType = CALLBACK_FOR_GPU_PROCESS;
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        } else if (SWITCH_PPAPI_BROKER_PROCESS.equals(processType)) {
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            inSandbox = false;
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ChildProcessConnection allocatedConnection = null;
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        synchronized (ChildProcessLauncher.class) {
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (inSandbox) {
371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                allocatedConnection = sSpareSandboxedConnection;
372ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                sSpareSandboxedConnection = null;
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (allocatedConnection == null) {
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            allocatedConnection = allocateBoundConnection(context, commandLine, inSandbox);
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            if (allocatedConnection == null) {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // Notify the native code so it can free the heap allocated callback.
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                nativeOnChildProcessStarted(clientContext, 0);
3805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                Log.e(TAG, "Allocation of new service failed.");
3815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                TraceEvent.end();
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                return;
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
385d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
3865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        Log.d(TAG, "Setting up connection to process: slot=" +
3875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                allocatedConnection.getServiceNumber());
3885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        triggerConnectionSetup(allocatedConnection, commandLine, childProcessId, filesToBeMapped,
3895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                callbackType, clientContext);
3905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        TraceEvent.end();
3915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
3925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
3935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    @VisibleForTesting
3945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    static void triggerConnectionSetup(
3955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            final ChildProcessConnection connection,
3965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            String[] commandLine,
3975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            int childProcessId,
3985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            FileDescriptorInfo[] filesToBeMapped,
3995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            int callbackType,
4005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            final long clientContext) {
401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        ChildProcessConnection.ConnectionCallback connectionCallback =
402d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                new ChildProcessConnection.ConnectionCallback() {
403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    @Override
404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    public void onConnected(int pid) {
405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        Log.d(TAG, "on connect callback, pid=" + pid + " context=" + clientContext);
406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        if (pid != NULL_PROCESS_HANDLE) {
407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                            sBindingManager.addNewConnection(pid, connection);
408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                            sServiceMap.put(pid, connection);
409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        }
4105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        // If the connection fails and pid == 0, the Java-side cleanup was already
4115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        // handled by DeathCallback. We still have to call back to native for
4125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        // cleanup there.
4135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        if (clientContext != 0) {  // Will be 0 in Java instrumentation tests.
4145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                            nativeOnChildProcessStarted(clientContext, pid);
4155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                        }
416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                    }
417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                };
418d3868032626d59662ff73b372b5d584c1d144c53Ben Murdoch
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // TODO(sievers): Revisit this as it doesn't correctly handle the utility process
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // assert callbackType != CALLBACK_FOR_UNKNOWN_PROCESS;
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        connection.setupConnection(commandLine,
4238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                   filesToBeMapped,
4244ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                                   createCallback(childProcessId, callbackType),
4258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                   connectionCallback,
4268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                   Linker.getSharedRelros());
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Terminates a child process. This may be called from any thread.
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * @param pid The pid (process handle) of the service connection obtained from {@link #start}.
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    @CalledByNative
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static void stop(int pid) {
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        Log.d(TAG, "stopping child connection: pid=" + pid);
437ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        ChildProcessConnection connection = sServiceMap.remove(pid);
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (connection == null) {
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            logPidWarning(pid, "Tried to stop non-existent connection");
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            return;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        sBindingManager.clearConnection(pid);
443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        connection.stop();
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        freeConnection(connection);
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /**
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * This implementation is used to receive callbacks from the remote service.
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
4504ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch    private static IChildProcessCallback createCallback(
4514ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch            final int childProcessId, final int callbackType) {
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return new IChildProcessCallback.Stub() {
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            /**
454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch             * This is called by the remote service regularly to tell us about new values. Note that
455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch             * IPC calls are dispatched through a thread pool running in each process, so the code
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch             * executing here will NOT be running in our main thread -- so, to update the UI, we
457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch             * need to use a Handler.
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             */
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            @Override
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            public void establishSurfacePeer(
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    int pid, Surface surface, int primaryID, int secondaryID) {
462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                // Do not allow a malicious renderer to connect to a producer. This is only used
463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                // from stream textures managed by the GPU process.
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (callbackType != CALLBACK_FOR_GPU_PROCESS) {
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    Log.e(TAG, "Illegal callback for non-GPU process.");
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    return;
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                nativeEstablishSurfacePeer(pid, surface, primaryID, secondaryID);
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            @Override
47346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            public SurfaceWrapper getViewSurface(int surfaceId) {
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                // Do not allow a malicious renderer to get to our view surface.
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                if (callbackType != CALLBACK_FOR_GPU_PROCESS) {
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    Log.e(TAG, "Illegal callback for non-GPU process.");
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    return null;
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                }
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                Surface surface = sViewSurfaceMap.get(surfaceId);
481c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                if (surface == null) {
482c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                    Log.e(TAG, "Invalid surfaceId.");
483c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                    return null;
484c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                }
48546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                assert surface.isValid();
48646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                return new SurfaceWrapper(surface);
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            }
4884ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
4894ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch            @Override
49046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            public SurfaceWrapper getSurfaceTextureSurface(int primaryId, int secondaryId) {
4914ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                if (callbackType != CALLBACK_FOR_RENDERER_PROCESS) {
4924ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                    Log.e(TAG, "Illegal callback for non-renderer process.");
4934ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                    return null;
4944ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                }
4954ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
4964ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                if (secondaryId != childProcessId) {
4974ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                    Log.e(TAG, "Illegal secondaryId for renderer process.");
4984ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                    return null;
4994ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch                }
5004ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch
501c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                Pair<Integer, Integer> key = new Pair<Integer, Integer>(primaryId, secondaryId);
502c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                // Note: This removes the surface and passes the ownership to the caller.
503c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                Surface surface = sSurfaceTextureSurfaceMap.remove(key);
504c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                if (surface == null) {
505c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                    Log.e(TAG, "Invalid Id for surface texture.");
506c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                    return null;
507c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                }
50846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                assert surface.isValid();
50946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                return new SurfaceWrapper(surface);
5104ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch            }
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        };
512f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)     static void logPidWarning(int pid, String message) {
5157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        // This class is effectively a no-op in single process mode, so don't log warnings there.
5167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        if (pid > 0 && !nativeIsSingleProcess()) {
5177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch            Log.w(TAG, message + ", pid=" + pid);
5187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        }
5197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
5207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    @VisibleForTesting
5225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    static ChildProcessConnection allocateBoundConnectionForTesting(Context context) {
5235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return allocateBoundConnection(context, null, true);
5245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
5255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /** @return the count of sandboxed connections managed by the allocator */
5275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    @VisibleForTesting
5285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    static int allocatedConnectionsCountForTesting() {
5295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return sSandboxedChildConnectionAllocator.allocatedConnectionsCountForTesting();
5305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
5315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    /** @return the count of services set up and working */
5335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    @VisibleForTesting
5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    static int connectedServicesCountForTesting() {
5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        return sServiceMap.size();
5365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
5375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    /**
5396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * Kills the child process for testing.
5406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * @return true iff the process was killed as expected
5416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     */
5426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    @VisibleForTesting
5436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    public static boolean crashProcessForTesting(int pid) {
5446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (sServiceMap.get(pid) == null) return false;
5456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        try {
5476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForTesting();
5486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        } catch (RemoteException ex) {
5496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            return false;
5506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        }
5516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
5526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return true;
5536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
5546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private static native void nativeOnChildProcessStarted(long clientContext, int pid);
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    private static native void nativeEstablishSurfacePeer(
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            int pid, Surface surface, int primaryID, int secondaryID);
5587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    private static native boolean nativeIsSingleProcess();
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
560