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