OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.content.pm.ApplicationInfo; | 8 import android.content.pm.ApplicationInfo; |
9 import android.content.pm.PackageManager; | 9 import android.content.pm.PackageManager; |
10 import android.graphics.SurfaceTexture; | 10 import android.graphics.SurfaceTexture; |
11 import android.os.RemoteException; | 11 import android.os.RemoteException; |
12 import android.util.Log; | 12 import android.util.Log; |
13 import android.util.Pair; | 13 import android.util.Pair; |
14 import android.view.Surface; | 14 import android.view.Surface; |
15 | 15 |
16 import org.chromium.base.CalledByNative; | 16 import org.chromium.base.CalledByNative; |
17 import org.chromium.base.JNINamespace; | 17 import org.chromium.base.JNINamespace; |
18 import org.chromium.base.ThreadUtils; | 18 import org.chromium.base.ThreadUtils; |
19 import org.chromium.base.TraceEvent; | 19 import org.chromium.base.TraceEvent; |
20 import org.chromium.base.VisibleForTesting; | 20 import org.chromium.base.VisibleForTesting; |
21 import org.chromium.base.library_loader.Linker; | 21 import org.chromium.base.library_loader.Linker; |
22 import org.chromium.content.app.ChildProcessService; | 22 import org.chromium.content.app.ChildProcessService; |
23 import org.chromium.content.app.ChromiumLinkerParams; | 23 import org.chromium.content.app.ChromiumLinkerParams; |
24 import org.chromium.content.app.PrivilegedProcessService; | 24 import org.chromium.content.app.PrivilegedProcessService; |
25 import org.chromium.content.app.SandboxedProcessService; | 25 import org.chromium.content.app.SandboxedProcessService; |
26 import org.chromium.content.common.IChildProcessCallback; | 26 import org.chromium.content.common.IChildProcessCallback; |
27 import org.chromium.content.common.SurfaceWrapper; | 27 import org.chromium.content.common.SurfaceWrapper; |
28 | 28 |
29 import java.util.ArrayList; | 29 import java.util.ArrayList; |
| 30 import java.util.LinkedList; |
30 import java.util.Map; | 31 import java.util.Map; |
| 32 import java.util.Queue; |
31 import java.util.concurrent.ConcurrentHashMap; | 33 import java.util.concurrent.ConcurrentHashMap; |
32 | 34 |
33 /** | 35 /** |
34 * This class provides the method to start/stop ChildProcess called by native. | 36 * This class provides the method to start/stop ChildProcess called by native. |
35 */ | 37 */ |
36 @JNINamespace("content") | 38 @JNINamespace("content") |
37 public class ChildProcessLauncher { | 39 public class ChildProcessLauncher { |
38 private static final String TAG = "ChildProcessLauncher"; | 40 private static final String TAG = "ChildProcessLauncher"; |
39 | 41 |
40 static final int CALLBACK_FOR_UNKNOWN_PROCESS = 0; | 42 static final int CALLBACK_FOR_UNKNOWN_PROCESS = 0; |
41 static final int CALLBACK_FOR_GPU_PROCESS = 1; | 43 static final int CALLBACK_FOR_GPU_PROCESS = 1; |
42 static final int CALLBACK_FOR_RENDERER_PROCESS = 2; | 44 static final int CALLBACK_FOR_RENDERER_PROCESS = 2; |
43 static final int CALLBACK_FOR_UTILITY_PROCESS = 3; | 45 static final int CALLBACK_FOR_UTILITY_PROCESS = 3; |
44 | 46 |
45 private static final String SWITCH_PROCESS_TYPE = "type"; | 47 private static final String SWITCH_PROCESS_TYPE = "type"; |
46 private static final String SWITCH_RENDERER_PROCESS = "renderer"; | 48 private static final String SWITCH_RENDERER_PROCESS = "renderer"; |
47 private static final String SWITCH_UTILITY_PROCESS = "utility"; | 49 private static final String SWITCH_UTILITY_PROCESS = "utility"; |
48 private static final String SWITCH_GPU_PROCESS = "gpu-process"; | 50 private static final String SWITCH_GPU_PROCESS = "gpu-process"; |
49 | 51 |
50 private static class ChildConnectionAllocator { | 52 private static class ChildConnectionAllocator { |
51 // Connections to services. Indices of the array correspond to the servi
ce numbers. | 53 // Connections to services. Indices of the array correspond to the servi
ce numbers. |
52 private final ChildProcessConnection[] mChildProcessConnections; | 54 private final ChildProcessConnection[] mChildProcessConnections; |
53 | 55 |
54 // The list of free (not bound) service indices. When looking for a free
service, the first | 56 // The list of free (not bound) service indices. |
55 // index in that list should be used. When a service is unbound, its ind
ex is added to the | |
56 // end of the list. This is so that we avoid immediately reusing the fre
ed service (see | |
57 // http://crbug.com/164069): the framework might keep a service process
alive when it's been | |
58 // unbound for a short time. If a new connection to the same service is
bound at that point, | |
59 // the process is reused and bad things happen (mostly static variables
are set when we | |
60 // don't expect them to). | |
61 // SHOULD BE ACCESSED WITH mConnectionLock. | 57 // SHOULD BE ACCESSED WITH mConnectionLock. |
62 private final ArrayList<Integer> mFreeConnectionIndices; | 58 private final ArrayList<Integer> mFreeConnectionIndices; |
63 private final Object mConnectionLock = new Object(); | 59 private final Object mConnectionLock = new Object(); |
64 | 60 |
65 private Class<? extends ChildProcessService> mChildClass; | 61 private Class<? extends ChildProcessService> mChildClass; |
66 private final boolean mInSandbox; | 62 private final boolean mInSandbox; |
67 | 63 |
68 public ChildConnectionAllocator(boolean inSandbox, int numChildServices)
{ | 64 public ChildConnectionAllocator(boolean inSandbox, int numChildServices)
{ |
69 mChildProcessConnections = new ChildProcessConnectionImpl[numChildSe
rvices]; | 65 mChildProcessConnections = new ChildProcessConnectionImpl[numChildSe
rvices]; |
70 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); | 66 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); |
71 for (int i = 0; i < numChildServices; i++) { | 67 for (int i = 0; i < numChildServices; i++) { |
72 mFreeConnectionIndices.add(i); | 68 mFreeConnectionIndices.add(i); |
73 } | 69 } |
74 mChildClass = | 70 mChildClass = |
75 inSandbox ? SandboxedProcessService.class : PrivilegedProcessSer
vice.class; | 71 inSandbox ? SandboxedProcessService.class : PrivilegedProcessSer
vice.class; |
76 mInSandbox = inSandbox; | 72 mInSandbox = inSandbox; |
77 } | 73 } |
78 | 74 |
79 public ChildProcessConnection allocate( | 75 public ChildProcessConnection allocate( |
80 Context context, ChildProcessConnection.DeathCallback deathCallb
ack, | 76 Context context, ChildProcessConnection.DeathCallback deathCallb
ack, |
81 ChromiumLinkerParams chromiumLinkerParams) { | 77 ChromiumLinkerParams chromiumLinkerParams) { |
82 synchronized (mConnectionLock) { | 78 synchronized (mConnectionLock) { |
83 if (mFreeConnectionIndices.isEmpty()) { | 79 if (mFreeConnectionIndices.isEmpty()) { |
84 Log.e(TAG, "Ran out of services to allocate."); | 80 Log.d(TAG, "Ran out of services to allocate."); |
85 assert false; | |
86 return null; | 81 return null; |
87 } | 82 } |
88 int slot = mFreeConnectionIndices.remove(0); | 83 int slot = mFreeConnectionIndices.remove(0); |
89 assert mChildProcessConnections[slot] == null; | 84 assert mChildProcessConnections[slot] == null; |
90 mChildProcessConnections[slot] = new ChildProcessConnectionImpl(
context, slot, | 85 mChildProcessConnections[slot] = new ChildProcessConnectionImpl(
context, slot, |
91 mInSandbox, deathCallback, mChildClass, chromiumLinkerPa
rams); | 86 mInSandbox, deathCallback, mChildClass, chromiumLinkerPa
rams); |
92 Log.d(TAG, "Allocator allocated a connection, sandbox: " + mInSa
ndbox | 87 Log.d(TAG, "Allocator allocated a connection, sandbox: " + mInSa
ndbox |
93 + ", slot: " + slot); | 88 + ", slot: " + slot); |
94 return mChildProcessConnections[slot]; | 89 return mChildProcessConnections[slot]; |
95 } | 90 } |
(...skipping 18 matching lines...) Expand all Loading... |
114 } | 109 } |
115 } | 110 } |
116 | 111 |
117 /** @return the count of connections managed by the allocator */ | 112 /** @return the count of connections managed by the allocator */ |
118 @VisibleForTesting | 113 @VisibleForTesting |
119 int allocatedConnectionsCountForTesting() { | 114 int allocatedConnectionsCountForTesting() { |
120 return mChildProcessConnections.length - mFreeConnectionIndices.size
(); | 115 return mChildProcessConnections.length - mFreeConnectionIndices.size
(); |
121 } | 116 } |
122 } | 117 } |
123 | 118 |
| 119 private static class PendingSpawnData { |
| 120 private final Context mContext; |
| 121 private final String[] mCommandLine; |
| 122 private final int mChildProcessId; |
| 123 private final FileDescriptorInfo[] mFilesToBeMapped; |
| 124 private final long mClientContext; |
| 125 private final int mCallbackType; |
| 126 private final boolean mInSandbox; |
| 127 |
| 128 private PendingSpawnData( |
| 129 Context context, |
| 130 String[] commandLine, |
| 131 int childProcessId, |
| 132 FileDescriptorInfo[] filesToBeMapped, |
| 133 long clientContext, |
| 134 int callbackType, |
| 135 boolean inSandbox) { |
| 136 mContext = context; |
| 137 mCommandLine = commandLine; |
| 138 mChildProcessId = childProcessId; |
| 139 mFilesToBeMapped = filesToBeMapped; |
| 140 mClientContext = clientContext; |
| 141 mCallbackType = callbackType; |
| 142 mInSandbox = inSandbox; |
| 143 } |
| 144 |
| 145 private Context context() { |
| 146 return mContext; |
| 147 } |
| 148 private String[] commandLine() { |
| 149 return mCommandLine; |
| 150 } |
| 151 private int childProcessId() { |
| 152 return mChildProcessId; |
| 153 } |
| 154 private FileDescriptorInfo[] filesToBeMapped() { |
| 155 return mFilesToBeMapped; |
| 156 } |
| 157 private long clientContext() { |
| 158 return mClientContext; |
| 159 } |
| 160 private int callbackType() { |
| 161 return mCallbackType; |
| 162 } |
| 163 private boolean inSandbox() { |
| 164 return mInSandbox; |
| 165 } |
| 166 } |
| 167 |
| 168 private static class PendingSpawnQueue { |
| 169 // The list of pending process spawn requests and its lock. |
| 170 private static Queue<PendingSpawnData> sPendingSpawns = |
| 171 new LinkedList<PendingSpawnData>(); |
| 172 static final Object sPendingSpawnsLock = new Object(); |
| 173 |
| 174 /** |
| 175 * Queue up a spawn requests to be processed once a free service is avai
lable. |
| 176 * Called when a spawn is requested while we are at the capacity. |
| 177 */ |
| 178 public void enqueue(final PendingSpawnData pendingSpawn) { |
| 179 synchronized (sPendingSpawnsLock) { |
| 180 sPendingSpawns.add(pendingSpawn); |
| 181 } |
| 182 } |
| 183 |
| 184 /** |
| 185 * Pop the next request from the queue. Called when a free service is av
ailable. |
| 186 * @return the next spawn request waiting in the queue. |
| 187 */ |
| 188 public PendingSpawnData dequeue() { |
| 189 synchronized (sPendingSpawnsLock) { |
| 190 return sPendingSpawns.poll(); |
| 191 } |
| 192 } |
| 193 |
| 194 /** @return the count of pending spawns in the queue */ |
| 195 public int size() { |
| 196 synchronized (sPendingSpawnsLock) { |
| 197 return sPendingSpawns.size(); |
| 198 } |
| 199 } |
| 200 } |
| 201 |
| 202 private static final PendingSpawnQueue sPendingSpawnQueue = new PendingSpawn
Queue(); |
| 203 |
124 // Service class for child process. As the default value it uses SandboxedPr
ocessService0 and | 204 // Service class for child process. As the default value it uses SandboxedPr
ocessService0 and |
125 // PrivilegedProcessService0. | 205 // PrivilegedProcessService0. |
126 private static ChildConnectionAllocator sSandboxedChildConnectionAllocator; | 206 private static ChildConnectionAllocator sSandboxedChildConnectionAllocator; |
127 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; | 207 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; |
128 | 208 |
129 private static final String NUM_SANDBOXED_SERVICES_KEY = | 209 private static final String NUM_SANDBOXED_SERVICES_KEY = |
130 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; | 210 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; |
131 private static final String NUM_PRIVILEGED_SERVICES_KEY = | 211 private static final String NUM_PRIVILEGED_SERVICES_KEY = |
132 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; | 212 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; |
133 | 213 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 String[] commandLine, boolean inSandbox) { | 291 String[] commandLine, boolean inSandbox) { |
212 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect
ion(); | 292 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect
ion(); |
213 ChildProcessConnection connection = | 293 ChildProcessConnection connection = |
214 allocateConnection(context, inSandbox, chromiumLinkerParams); | 294 allocateConnection(context, inSandbox, chromiumLinkerParams); |
215 if (connection != null) { | 295 if (connection != null) { |
216 connection.start(commandLine); | 296 connection.start(commandLine); |
217 } | 297 } |
218 return connection; | 298 return connection; |
219 } | 299 } |
220 | 300 |
| 301 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; |
| 302 |
221 private static void freeConnection(ChildProcessConnection connection) { | 303 private static void freeConnection(ChildProcessConnection connection) { |
222 getConnectionAllocator(connection.isInSandbox()).free(connection); | 304 // Freeing a service should be delayed. This is so that we avoid immedia
tely reusing the |
| 305 // freed service (see http://crbug.com/164069): the framework might keep
a service process |
| 306 // alive when it's been unbound for a short time. If a new connection to
the same service |
| 307 // is bound at that point, the process is reused and bad things happen (
mostly static |
| 308 // variables are set when we don't expect them to). |
| 309 final ChildProcessConnection conn = connection; |
| 310 ThreadUtils.postOnUiThreadDelayed(new Runnable() { |
| 311 @Override |
| 312 public void run() { |
| 313 getConnectionAllocator(conn.isInSandbox()).free(conn); |
| 314 |
| 315 final PendingSpawnData pendingSpawn = sPendingSpawnQueue.dequeue
(); |
| 316 if (pendingSpawn != null) { |
| 317 new Thread(new Runnable() { |
| 318 @Override |
| 319 public void run() { |
| 320 startInternal(pendingSpawn.context(), pendingSpawn.c
ommandLine(), |
| 321 pendingSpawn.childProcessId(), pendingSpawn.
filesToBeMapped(), |
| 322 pendingSpawn.clientContext(), pendingSpawn.c
allbackType(), |
| 323 pendingSpawn.inSandbox()); |
| 324 } |
| 325 }).start(); |
| 326 } |
| 327 } |
| 328 }, FREE_CONNECTION_DELAY_MILLIS); |
223 } | 329 } |
224 | 330 |
225 // Represents an invalid process handle; same as base/process/process.h kNul
lProcessHandle. | 331 // Represents an invalid process handle; same as base/process/process.h kNul
lProcessHandle. |
226 private static final int NULL_PROCESS_HANDLE = 0; | 332 private static final int NULL_PROCESS_HANDLE = 0; |
227 | 333 |
228 // Map from pid to ChildService connection. | 334 // Map from pid to ChildService connection. |
229 private static Map<Integer, ChildProcessConnection> sServiceMap = | 335 private static Map<Integer, ChildProcessConnection> sServiceMap = |
230 new ConcurrentHashMap<Integer, ChildProcessConnection>(); | 336 new ConcurrentHashMap<Integer, ChildProcessConnection>(); |
231 | 337 |
232 // A pre-allocated and pre-bound connection ready for connection setup, or n
ull. | 338 // A pre-allocated and pre-bound connection ready for connection setup, or n
ull. |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 */ | 486 */ |
381 @CalledByNative | 487 @CalledByNative |
382 static void start( | 488 static void start( |
383 Context context, | 489 Context context, |
384 final String[] commandLine, | 490 final String[] commandLine, |
385 int childProcessId, | 491 int childProcessId, |
386 int[] fileIds, | 492 int[] fileIds, |
387 int[] fileFds, | 493 int[] fileFds, |
388 boolean[] fileAutoClose, | 494 boolean[] fileAutoClose, |
389 long clientContext) { | 495 long clientContext) { |
| 496 assert fileIds.length == fileFds.length && fileFds.length == fileAutoClo
se.length; |
| 497 FileDescriptorInfo[] filesToBeMapped = new FileDescriptorInfo[fileFds.le
ngth]; |
| 498 for (int i = 0; i < fileFds.length; i++) { |
| 499 filesToBeMapped[i] = |
| 500 new FileDescriptorInfo(fileIds[i], fileFds[i], fileAutoClose
[i]); |
| 501 } |
| 502 assert clientContext != 0; |
| 503 |
| 504 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; |
| 505 boolean inSandbox = true; |
| 506 String processType = getSwitchValue(commandLine, SWITCH_PROCESS_TYPE); |
| 507 if (SWITCH_RENDERER_PROCESS.equals(processType)) { |
| 508 callbackType = CALLBACK_FOR_RENDERER_PROCESS; |
| 509 } else if (SWITCH_GPU_PROCESS.equals(processType)) { |
| 510 callbackType = CALLBACK_FOR_GPU_PROCESS; |
| 511 inSandbox = false; |
| 512 } else if (SWITCH_UTILITY_PROCESS.equals(processType)) { |
| 513 // We only support sandboxed right now. |
| 514 callbackType = CALLBACK_FOR_UTILITY_PROCESS; |
| 515 } else { |
| 516 assert false; |
| 517 } |
| 518 |
| 519 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli
entContext, |
| 520 callbackType, inSandbox); |
| 521 } |
| 522 |
| 523 private static void startInternal( |
| 524 Context context, |
| 525 final String[] commandLine, |
| 526 int childProcessId, |
| 527 FileDescriptorInfo[] filesToBeMapped, |
| 528 long clientContext, |
| 529 int callbackType, |
| 530 boolean inSandbox) { |
390 try { | 531 try { |
391 TraceEvent.begin("ChildProcessLauncher.start"); | 532 TraceEvent.begin("ChildProcessLauncher.startInternal"); |
392 assert fileIds.length == fileFds.length && fileFds.length == fileAut
oClose.length; | |
393 FileDescriptorInfo[] filesToBeMapped = new FileDescriptorInfo[fileFd
s.length]; | |
394 for (int i = 0; i < fileFds.length; i++) { | |
395 filesToBeMapped[i] = | |
396 new FileDescriptorInfo(fileIds[i], fileFds[i], fileAutoC
lose[i]); | |
397 } | |
398 assert clientContext != 0; | |
399 | |
400 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; | |
401 boolean inSandbox = true; | |
402 String processType = getSwitchValue(commandLine, SWITCH_PROCESS_TYPE
); | |
403 if (SWITCH_RENDERER_PROCESS.equals(processType)) { | |
404 callbackType = CALLBACK_FOR_RENDERER_PROCESS; | |
405 } else if (SWITCH_GPU_PROCESS.equals(processType)) { | |
406 callbackType = CALLBACK_FOR_GPU_PROCESS; | |
407 inSandbox = false; | |
408 } else if (SWITCH_UTILITY_PROCESS.equals(processType)) { | |
409 // We only support sandboxed right now. | |
410 callbackType = CALLBACK_FOR_UTILITY_PROCESS; | |
411 } else { | |
412 assert false; | |
413 } | |
414 | 533 |
415 ChildProcessConnection allocatedConnection = null; | 534 ChildProcessConnection allocatedConnection = null; |
416 synchronized (ChildProcessLauncher.class) { | 535 synchronized (ChildProcessLauncher.class) { |
417 if (inSandbox) { | 536 if (inSandbox) { |
418 allocatedConnection = sSpareSandboxedConnection; | 537 allocatedConnection = sSpareSandboxedConnection; |
419 sSpareSandboxedConnection = null; | 538 sSpareSandboxedConnection = null; |
420 } | 539 } |
421 } | 540 } |
422 if (allocatedConnection == null) { | 541 if (allocatedConnection == null) { |
423 allocatedConnection = allocateBoundConnection(context, commandLi
ne, inSandbox); | 542 allocatedConnection = allocateBoundConnection(context, commandLi
ne, inSandbox); |
424 if (allocatedConnection == null) { | 543 if (allocatedConnection == null) { |
425 // Notify the native code so it can free the heap allocated
callback. | 544 Log.d(TAG, "Allocation of new service failed. Queuing up pen
ding spawn."); |
426 nativeOnChildProcessStarted(clientContext, 0); | 545 sPendingSpawnQueue.enqueue(new PendingSpawnData(context, com
mandLine, |
427 Log.e(TAG, "Allocation of new service failed."); | 546 childProcessId, filesToBeMapped, clientContext, call
backType, |
| 547 inSandbox)); |
428 return; | 548 return; |
429 } | 549 } |
430 } | 550 } |
431 | 551 |
432 Log.d(TAG, "Setting up connection to process: slot=" | 552 Log.d(TAG, "Setting up connection to process: slot=" |
433 + allocatedConnection.getServiceNumber()); | 553 + allocatedConnection.getServiceNumber()); |
434 triggerConnectionSetup(allocatedConnection, commandLine, childProces
sId, | 554 triggerConnectionSetup(allocatedConnection, commandLine, childProces
sId, |
435 filesToBeMapped, callbackType, clientContext); | 555 filesToBeMapped, callbackType, clientContext); |
436 } finally { | 556 } finally { |
437 TraceEvent.end("ChildProcessLauncher.start"); | 557 TraceEvent.end("ChildProcessLauncher.startInternal"); |
438 } | 558 } |
439 } | 559 } |
440 | 560 |
441 @VisibleForTesting | 561 @VisibleForTesting |
442 static void triggerConnectionSetup( | 562 static void triggerConnectionSetup( |
443 final ChildProcessConnection connection, | 563 final ChildProcessConnection connection, |
444 String[] commandLine, | 564 String[] commandLine, |
445 int childProcessId, | 565 int childProcessId, |
446 FileDescriptorInfo[] filesToBeMapped, | 566 FileDescriptorInfo[] filesToBeMapped, |
447 int callbackType, | 567 int callbackType, |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 if (pid > 0 && !nativeIsSingleProcess()) { | 693 if (pid > 0 && !nativeIsSingleProcess()) { |
574 Log.w(TAG, message + ", pid=" + pid); | 694 Log.w(TAG, message + ", pid=" + pid); |
575 } | 695 } |
576 } | 696 } |
577 | 697 |
578 @VisibleForTesting | 698 @VisibleForTesting |
579 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont
ext) { | 699 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont
ext) { |
580 return allocateBoundConnection(context, null, true); | 700 return allocateBoundConnection(context, null, true); |
581 } | 701 } |
582 | 702 |
| 703 /** |
| 704 * Queue up a spawn requests for testing. |
| 705 */ |
| 706 @VisibleForTesting |
| 707 static void enqueuePendingSpawnForTesting(Context context) { |
| 708 sPendingSpawnQueue.enqueue(new PendingSpawnData(context, new String[0],
1, |
| 709 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, tru
e)); |
| 710 } |
| 711 |
583 /** @return the count of sandboxed connections managed by the allocator */ | 712 /** @return the count of sandboxed connections managed by the allocator */ |
584 @VisibleForTesting | 713 @VisibleForTesting |
585 static int allocatedConnectionsCountForTesting(Context context) { | 714 static int allocatedConnectionsCountForTesting(Context context) { |
586 initConnectionAllocatorsIfNecessary(context); | 715 initConnectionAllocatorsIfNecessary(context); |
587 return sSandboxedChildConnectionAllocator.allocatedConnectionsCountForTe
sting(); | 716 return sSandboxedChildConnectionAllocator.allocatedConnectionsCountForTe
sting(); |
588 } | 717 } |
589 | 718 |
590 /** @return the count of services set up and working */ | 719 /** @return the count of services set up and working */ |
591 @VisibleForTesting | 720 @VisibleForTesting |
592 static int connectedServicesCountForTesting() { | 721 static int connectedServicesCountForTesting() { |
593 return sServiceMap.size(); | 722 return sServiceMap.size(); |
594 } | 723 } |
595 | 724 |
| 725 /** @return the count of pending spawns in the queue */ |
| 726 @VisibleForTesting |
| 727 static int pendingSpawnsCountForTesting() { |
| 728 return sPendingSpawnQueue.size(); |
| 729 } |
| 730 |
596 /** | 731 /** |
597 * Kills the child process for testing. | 732 * Kills the child process for testing. |
598 * @return true iff the process was killed as expected | 733 * @return true iff the process was killed as expected |
599 */ | 734 */ |
600 @VisibleForTesting | 735 @VisibleForTesting |
601 public static boolean crashProcessForTesting(int pid) { | 736 public static boolean crashProcessForTesting(int pid) { |
602 if (sServiceMap.get(pid) == null) return false; | 737 if (sServiceMap.get(pid) == null) return false; |
603 | 738 |
604 try { | 739 try { |
605 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT
esting(); | 740 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT
esting(); |
606 } catch (RemoteException ex) { | 741 } catch (RemoteException ex) { |
607 return false; | 742 return false; |
608 } | 743 } |
609 | 744 |
610 return true; | 745 return true; |
611 } | 746 } |
612 | 747 |
613 private static native void nativeOnChildProcessStarted(long clientContext, i
nt pid); | 748 private static native void nativeOnChildProcessStarted(long clientContext, i
nt pid); |
614 private static native void nativeEstablishSurfacePeer( | 749 private static native void nativeEstablishSurfacePeer( |
615 int pid, Surface surface, int primaryID, int secondaryID); | 750 int pid, Surface surface, int primaryID, int secondaryID); |
616 private static native boolean nativeIsSingleProcess(); | 751 private static native boolean nativeIsSingleProcess(); |
617 } | 752 } |
OLD | NEW |