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.annotation.SuppressLint; | 7 import android.annotation.SuppressLint; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.content.Intent; | 9 import android.content.Intent; |
10 import android.content.pm.ApplicationInfo; | 10 import android.content.pm.ApplicationInfo; |
11 import android.content.pm.PackageManager; | 11 import android.content.pm.PackageManager; |
12 import android.graphics.SurfaceTexture; | 12 import android.graphics.SurfaceTexture; |
13 import android.os.Build; | 13 import android.os.Build; |
14 import android.os.Bundle; | 14 import android.os.Bundle; |
15 import android.os.ParcelFileDescriptor; | 15 import android.os.ParcelFileDescriptor; |
16 import android.os.RemoteException; | 16 import android.os.RemoteException; |
17 import android.text.TextUtils; | 17 import android.text.TextUtils; |
18 import android.util.Pair; | 18 import android.util.Pair; |
19 import android.view.Surface; | 19 import android.view.Surface; |
20 | 20 |
21 import org.chromium.base.CommandLine; | 21 import org.chromium.base.CommandLine; |
22 import org.chromium.base.CpuFeatures; | 22 import org.chromium.base.CpuFeatures; |
23 import org.chromium.base.Log; | 23 import org.chromium.base.Log; |
24 import org.chromium.base.ThreadUtils; | 24 import org.chromium.base.ThreadUtils; |
25 import org.chromium.base.TraceEvent; | 25 import org.chromium.base.TraceEvent; |
26 import org.chromium.base.VisibleForTesting; | 26 import org.chromium.base.VisibleForTesting; |
27 import org.chromium.base.annotations.CalledByNative; | 27 import org.chromium.base.annotations.CalledByNative; |
28 import org.chromium.base.annotations.JNINamespace; | 28 import org.chromium.base.annotations.JNINamespace; |
29 import org.chromium.base.library_loader.LibraryProcessType; | |
29 import org.chromium.base.library_loader.Linker; | 30 import org.chromium.base.library_loader.Linker; |
30 import org.chromium.content.app.ChildProcessService; | 31 import org.chromium.content.app.ChildProcessService; |
31 import org.chromium.content.app.ChromiumLinkerParams; | 32 import org.chromium.content.app.ChromiumLinkerParams; |
32 import org.chromium.content.app.DownloadProcessService; | 33 import org.chromium.content.app.DownloadProcessService; |
33 import org.chromium.content.app.PrivilegedProcessService; | 34 import org.chromium.content.app.PrivilegedProcessService; |
34 import org.chromium.content.app.SandboxedProcessService; | 35 import org.chromium.content.app.SandboxedProcessService; |
35 import org.chromium.content.common.ContentSwitches; | 36 import org.chromium.content.common.ContentSwitches; |
36 import org.chromium.content.common.IChildProcessCallback; | 37 import org.chromium.content.common.IChildProcessCallback; |
37 import org.chromium.content.common.SurfaceWrapper; | 38 import org.chromium.content.common.SurfaceWrapper; |
38 | 39 |
39 import java.io.IOException; | 40 import java.io.IOException; |
40 import java.util.ArrayList; | 41 import java.util.ArrayList; |
42 import java.util.HashMap; | |
41 import java.util.LinkedList; | 43 import java.util.LinkedList; |
42 import java.util.Map; | 44 import java.util.Map; |
43 import java.util.Queue; | 45 import java.util.Queue; |
44 import java.util.concurrent.ConcurrentHashMap; | 46 import java.util.concurrent.ConcurrentHashMap; |
45 | 47 |
46 /** | 48 /** |
47 * This class provides the method to start/stop ChildProcess called by native. | 49 * This class provides the method to start/stop ChildProcess called by native. |
48 */ | 50 */ |
49 @JNINamespace("content") | 51 @JNINamespace("content") |
50 public class ChildProcessLauncher { | 52 public class ChildProcessLauncher { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
118 } | 120 } |
119 } | 121 } |
120 } | 122 } |
121 | 123 |
122 public boolean isFreeConnectionAvailable() { | 124 public boolean isFreeConnectionAvailable() { |
123 synchronized (mConnectionLock) { | 125 synchronized (mConnectionLock) { |
124 return !mFreeConnectionIndices.isEmpty(); | 126 return !mFreeConnectionIndices.isEmpty(); |
125 } | 127 } |
126 } | 128 } |
127 | 129 |
128 /** @return the count of connections managed by the allocator */ | 130 /** Returns the count of connections managed by the allocator */ |
pkotwicz
2016/05/28 01:04:14
Why this change?
Xi Han
2016/05/30 19:59:30
Due to the java style guide. I will revert them ba
pkotwicz
2016/05/31 00:38:58
My bad. Yes, the Java style guide says you should
| |
129 @VisibleForTesting | 131 @VisibleForTesting |
130 int allocatedConnectionsCountForTesting() { | 132 int allocatedConnectionsCountForTesting() { |
131 return mChildProcessConnections.length - mFreeConnectionIndices.size (); | 133 return mChildProcessConnections.length - mFreeConnectionIndices.size (); |
132 } | 134 } |
133 } | 135 } |
134 | 136 |
135 private static class PendingSpawnData { | 137 private static class PendingSpawnData { |
136 private final Context mContext; | 138 private final Context mContext; |
137 private final String[] mCommandLine; | 139 private final String[] mCommandLine; |
138 private final int mChildProcessId; | 140 private final int mChildProcessId; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
199 | 201 |
200 /** | 202 /** |
201 * Pop the next request from the queue. Called when a free service is av ailable. | 203 * Pop the next request from the queue. Called when a free service is av ailable. |
202 * @return the next spawn request waiting in the queue. | 204 * @return the next spawn request waiting in the queue. |
203 */ | 205 */ |
204 public PendingSpawnData dequeueLocked() { | 206 public PendingSpawnData dequeueLocked() { |
205 assert Thread.holdsLock(sPendingSpawnsLock); | 207 assert Thread.holdsLock(sPendingSpawnsLock); |
206 return sPendingSpawns.poll(); | 208 return sPendingSpawns.poll(); |
207 } | 209 } |
208 | 210 |
209 /** @return the count of pending spawns in the queue */ | 211 /** Returns the count of pending spawns in the queue */ |
pkotwicz
2016/05/28 01:04:14
Why this change?
Xi Han
2016/05/30 19:59:31
Done.
| |
210 public int sizeLocked() { | 212 public int sizeLocked() { |
211 assert Thread.holdsLock(sPendingSpawnsLock); | 213 assert Thread.holdsLock(sPendingSpawnsLock); |
212 return sPendingSpawns.size(); | 214 return sPendingSpawns.size(); |
213 } | 215 } |
214 } | 216 } |
215 | 217 |
216 private static final PendingSpawnQueue sPendingSpawnQueue = new PendingSpawn Queue(); | 218 private static final PendingSpawnQueue sPendingSpawnQueue = new PendingSpawn Queue(); |
217 | 219 |
218 // Service class for child process. As the default value it uses SandboxedPr ocessService0 and | 220 // Service class for child process. |
219 // PrivilegedProcessService0. | 221 // Map from package name to ChildConnectionAllocator; |
220 private static ChildConnectionAllocator sSandboxedChildConnectionAllocator; | 222 private static Map<String, ChildConnectionAllocator> sSandboxedChildConnecti onAllocatorMap; |
223 // As the default value it uses PrivilegedProcessService0. | |
221 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; | 224 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; |
222 | 225 |
223 private static final String NUM_SANDBOXED_SERVICES_KEY = | 226 private static final String NUM_SANDBOXED_SERVICES_KEY = |
224 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; | 227 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; |
225 private static final String NUM_PRIVILEGED_SERVICES_KEY = | 228 private static final String NUM_PRIVILEGED_SERVICES_KEY = |
226 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; | 229 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; |
227 // Overrides the number of available sandboxed services. | 230 // Overrides the number of available sandboxed services. |
228 @VisibleForTesting | 231 @VisibleForTesting |
229 public static final String SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING = "num- sandboxed-services"; | 232 public static final String SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING = "num- sandboxed-services"; |
230 | 233 |
231 private static int getNumberOfServices(Context context, boolean inSandbox) { | 234 private static int getNumberOfServices(Context context, boolean inSandbox, S tring packageName) { |
232 try { | 235 try { |
233 PackageManager packageManager = context.getPackageManager(); | 236 PackageManager packageManager = context.getPackageManager(); |
234 ChildProcessCreationParams childProcessCreationParams = | |
235 ChildProcessCreationParams.get(); | |
236 final String packageName = childProcessCreationParams != null | |
237 ? childProcessCreationParams.getPackageName() : context.getP ackageName(); | |
238 ApplicationInfo appInfo = packageManager.getApplicationInfo(packageN ame, | 237 ApplicationInfo appInfo = packageManager.getApplicationInfo(packageN ame, |
239 PackageManager.GET_META_DATA); | 238 PackageManager.GET_META_DATA); |
240 int numServices = appInfo.metaData.getInt(inSandbox ? NUM_SANDBOXED_ SERVICES_KEY | 239 int numServices = -1; |
241 : NUM_PRIVILEGED_SERVICES_KEY, -1); | 240 if (appInfo.metaData != null) { |
241 numServices = appInfo.metaData.getInt( | |
242 inSandbox ? NUM_SANDBOXED_SERVICES_KEY : NUM_PRIVILEGED_ SERVICES_KEY, -1); | |
243 } | |
242 if (inSandbox | 244 if (inSandbox |
243 && CommandLine.getInstance().hasSwitch( | 245 && CommandLine.getInstance().hasSwitch( |
244 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) { | 246 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) { |
245 String value = CommandLine.getInstance().getSwitchValue( | 247 String value = CommandLine.getInstance().getSwitchValue( |
246 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING); | 248 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING); |
247 if (!TextUtils.isEmpty(value)) { | 249 if (!TextUtils.isEmpty(value)) { |
248 try { | 250 try { |
249 numServices = Integer.parseInt(value); | 251 numServices = Integer.parseInt(value); |
250 } catch (NumberFormatException e) { | 252 } catch (NumberFormatException e) { |
251 Log.w(TAG, "The value of --num-sandboxed-services is for matted wrongly: " | 253 Log.w(TAG, "The value of --num-sandboxed-services is for matted wrongly: " |
252 + value); | 254 + value); |
253 } | 255 } |
254 } | 256 } |
255 } | 257 } |
256 if (numServices < 0) { | 258 if (numServices < 0) { |
257 throw new RuntimeException("Illegal meta data value for number o f child services"); | 259 throw new RuntimeException("Illegal meta data value for number o f child services"); |
258 } | 260 } |
259 return numServices; | 261 return numServices; |
260 } catch (PackageManager.NameNotFoundException e) { | 262 } catch (PackageManager.NameNotFoundException e) { |
261 throw new RuntimeException("Could not get application info"); | 263 throw new RuntimeException("Could not get application info"); |
262 } | 264 } |
263 } | 265 } |
264 | 266 |
265 private static void initConnectionAllocatorsIfNecessary(Context context) { | 267 private static void initConnectionAllocatorsIfNecessary( |
268 Context context, boolean inSandbox, String packageName) { | |
266 synchronized (ChildProcessLauncher.class) { | 269 synchronized (ChildProcessLauncher.class) { |
267 if (sSandboxedChildConnectionAllocator == null) { | 270 if (inSandbox) { |
268 sSandboxedChildConnectionAllocator = | 271 if (sSandboxedChildConnectionAllocatorMap == null) { |
269 new ChildConnectionAllocator(true, getNumberOfServices(c ontext, true)); | 272 sSandboxedChildConnectionAllocatorMap = |
273 new HashMap<String, ChildConnectionAllocator>(); | |
274 } | |
275 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageNa me)) { | |
276 Log.w(TAG, "Create a new ChildConnectionAllocator with packa ge name = %s," | |
277 + " inSandbox = true", | |
278 packageName); | |
279 sSandboxedChildConnectionAllocatorMap.put(packageName, | |
280 new ChildConnectionAllocator(true, getNumberOfServic es(context, | |
281 inSandbox , packageName))); | |
282 } | |
283 } else if (sPrivilegedChildConnectionAllocator == null) { | |
284 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat or( | |
285 false, getNumberOfServices(context, false, packageName)) ; | |
270 } | 286 } |
271 if (sPrivilegedChildConnectionAllocator == null) { | 287 // TODO(pkotwicz|hanxi): Figure out when old allocators should be re moved from |
272 sPrivilegedChildConnectionAllocator = | 288 // {@code sSandboxedChildConnectionAllocatorMap}. |
273 new ChildConnectionAllocator(false, getNumberOfServices( context, false)); | |
274 } | |
275 } | 289 } |
276 } | 290 } |
277 | 291 |
278 private static ChildConnectionAllocator getConnectionAllocator(boolean inSan dbox) { | 292 private static ChildConnectionAllocator getConnectionAllocator( |
279 return inSandbox | 293 String packageName, boolean inSandbox) { |
280 ? sSandboxedChildConnectionAllocator : sPrivilegedChildConnectio nAllocator; | 294 if (!inSandbox) { |
295 return sPrivilegedChildConnectionAllocator; | |
296 } | |
297 return sSandboxedChildConnectionAllocatorMap.get(packageName); | |
281 } | 298 } |
282 | 299 |
283 private static ChildProcessConnection allocateConnection(Context context, bo olean inSandbox, | 300 private static ChildProcessConnection allocateConnection(Context context, bo olean inSandbox, |
284 ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForegroun d) { | 301 ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForegroun d, |
302 ChildProcessCreationParams creationParams) { | |
285 ChildProcessConnection.DeathCallback deathCallback = | 303 ChildProcessConnection.DeathCallback deathCallback = |
286 new ChildProcessConnection.DeathCallback() { | 304 new ChildProcessConnection.DeathCallback() { |
287 @Override | 305 @Override |
288 public void onChildProcessDied(ChildProcessConnection connec tion) { | 306 public void onChildProcessDied(ChildProcessConnection connec tion) { |
289 if (connection.getPid() != 0) { | 307 if (connection.getPid() != 0) { |
290 stop(connection.getPid()); | 308 stop(connection.getPid()); |
291 } else { | 309 } else { |
292 freeConnection(connection); | 310 freeConnection(connection); |
293 } | 311 } |
294 } | 312 } |
295 }; | 313 }; |
296 initConnectionAllocatorsIfNecessary(context); | 314 String packageName = creationParams.getPackageName(); |
297 return getConnectionAllocator(inSandbox).allocate(context, deathCallback , | 315 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName); |
298 chromiumLinkerParams, alwaysInForeground, ChildProcessCreationPa rams.get()); | 316 return getConnectionAllocator(packageName, inSandbox) |
317 .allocate(context, deathCallback, chromiumLinkerParams, alwaysIn Foreground, | |
318 creationParams); | |
299 } | 319 } |
300 | 320 |
301 private static boolean sLinkerInitialized = false; | 321 private static boolean sLinkerInitialized = false; |
302 private static long sLinkerLoadAddress = 0; | 322 private static long sLinkerLoadAddress = 0; |
303 | 323 |
304 private static ChromiumLinkerParams getLinkerParamsForNewConnection() { | 324 private static ChromiumLinkerParams getLinkerParamsForNewConnection() { |
305 if (!sLinkerInitialized) { | 325 if (!sLinkerInitialized) { |
306 if (Linker.isUsed()) { | 326 if (Linker.isUsed()) { |
307 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress(); | 327 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress(); |
308 if (sLinkerLoadAddress == 0) { | 328 if (sLinkerLoadAddress == 0) { |
(...skipping 13 matching lines...) Expand all Loading... | |
322 waitForSharedRelros, | 342 waitForSharedRelros, |
323 linker.getTestRunnerClassNameForTest ing(), | 343 linker.getTestRunnerClassNameForTest ing(), |
324 linker.getImplementationForTesting() ); | 344 linker.getImplementationForTesting() ); |
325 } else { | 345 } else { |
326 return new ChromiumLinkerParams(sLinkerLoadAddress, | 346 return new ChromiumLinkerParams(sLinkerLoadAddress, |
327 waitForSharedRelros); | 347 waitForSharedRelros); |
328 } | 348 } |
329 } | 349 } |
330 | 350 |
331 private static ChildProcessConnection allocateBoundConnection(Context contex t, | 351 private static ChildProcessConnection allocateBoundConnection(Context contex t, |
332 String[] commandLine, boolean inSandbox, boolean alwaysInForeground) { | 352 String[] commandLine, boolean inSandbox, boolean alwaysInForeground, |
353 ChildProcessCreationParams creationParams) { | |
333 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect ion(); | 354 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect ion(); |
334 ChildProcessConnection connection = allocateConnection(context, inSandbo x, | 355 ChildProcessConnection connection = allocateConnection( |
335 chromiumLinkerParams, alwaysInForeground); | 356 context, inSandbox, chromiumLinkerParams, alwaysInForeground, cr eationParams); |
336 if (connection != null) { | 357 if (connection != null) { |
337 connection.start(commandLine); | 358 connection.start(commandLine); |
338 | 359 |
339 if (inSandbox && !sSandboxedChildConnectionAllocator.isFreeConnectio nAvailable()) { | 360 if (inSandbox |
361 && !sSandboxedChildConnectionAllocatorMap.get(creationParams .getPackageName()) | |
pkotwicz
2016/05/28 01:04:14
Nit: Use getConnectionAllocator() instead of sSand
Xi Han
2016/05/30 19:59:31
Done.
| |
362 .isFreeConnectionAvailable()) { | |
340 // Proactively releases all the moderate bindings once all the s andboxed services | 363 // Proactively releases all the moderate bindings once all the s andboxed services |
341 // are allocated, which will be very likely to have some of them killed by OOM | 364 // are allocated, which will be very likely to have some of them killed by OOM |
342 // killer. | 365 // killer. |
343 sBindingManager.releaseAllModerateBindings(); | 366 sBindingManager.releaseAllModerateBindings(); |
344 } | 367 } |
345 } | 368 } |
346 return connection; | 369 return connection; |
347 } | 370 } |
348 | 371 |
349 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; | 372 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; |
(...skipping 13 matching lines...) Expand all Loading... | |
363 @Override | 386 @Override |
364 public void run() { | 387 public void run() { |
365 final PendingSpawnData pendingSpawn = freeConnectionAndDequeuePe nding(conn); | 388 final PendingSpawnData pendingSpawn = freeConnectionAndDequeuePe nding(conn); |
366 if (pendingSpawn != null) { | 389 if (pendingSpawn != null) { |
367 new Thread(new Runnable() { | 390 new Thread(new Runnable() { |
368 @Override | 391 @Override |
369 public void run() { | 392 public void run() { |
370 startInternal(pendingSpawn.context(), pendingSpawn.c ommandLine(), | 393 startInternal(pendingSpawn.context(), pendingSpawn.c ommandLine(), |
371 pendingSpawn.childProcessId(), pendingSpawn. filesToBeMapped(), | 394 pendingSpawn.childProcessId(), pendingSpawn. filesToBeMapped(), |
372 pendingSpawn.clientContext(), pendingSpawn.c allbackType(), | 395 pendingSpawn.clientContext(), pendingSpawn.c allbackType(), |
373 pendingSpawn.inSandbox()); | 396 pendingSpawn.inSandbox(), conn.getCreationPa rams()); |
pkotwicz
2016/05/28 01:04:15
The params of the freed connection may be differen
Xi Han
2016/05/30 19:59:31
Good catch. Store ChildProcessCreationParams in Pe
| |
374 } | 397 } |
375 }).start(); | 398 }).start(); |
376 } | 399 } |
377 } | 400 } |
378 }, FREE_CONNECTION_DELAY_MILLIS); | 401 }, FREE_CONNECTION_DELAY_MILLIS); |
379 } | 402 } |
380 | 403 |
381 private static PendingSpawnData freeConnectionAndDequeuePending(ChildProcess Connection conn) { | 404 private static PendingSpawnData freeConnectionAndDequeuePending(ChildProcess Connection conn) { |
382 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { | 405 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { |
383 getConnectionAllocator(conn.isInSandbox()).free(conn); | 406 getConnectionAllocator(conn.getCreationParams().getPackageName(), co nn.isInSandbox()) |
407 .free(conn); | |
384 return sPendingSpawnQueue.dequeueLocked(); | 408 return sPendingSpawnQueue.dequeueLocked(); |
385 } | 409 } |
386 } | 410 } |
387 | 411 |
388 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle. | 412 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle. |
389 private static final int NULL_PROCESS_HANDLE = 0; | 413 private static final int NULL_PROCESS_HANDLE = 0; |
390 | 414 |
391 // Map from pid to ChildService connection. | 415 // Map from pid to ChildService connection. |
392 private static Map<Integer, ChildProcessConnection> sServiceMap = | 416 private static Map<Integer, ChildProcessConnection> sServiceMap = |
393 new ConcurrentHashMap<Integer, ChildProcessConnection>(); | 417 new ConcurrentHashMap<Integer, ChildProcessConnection>(); |
(...skipping 13 matching lines...) Expand all Loading... | |
407 new ConcurrentHashMap<Pair<Integer, Integer>, Surface>(); | 431 new ConcurrentHashMap<Pair<Integer, Integer>, Surface>(); |
408 | 432 |
409 // Whether the main application is currently brought to the foreground. | 433 // Whether the main application is currently brought to the foreground. |
410 private static boolean sApplicationInForeground = true; | 434 private static boolean sApplicationInForeground = true; |
411 | 435 |
412 @VisibleForTesting | 436 @VisibleForTesting |
413 public static void setBindingManagerForTesting(BindingManager manager) { | 437 public static void setBindingManagerForTesting(BindingManager manager) { |
414 sBindingManager = manager; | 438 sBindingManager = manager; |
415 } | 439 } |
416 | 440 |
417 /** @return true iff the child process is protected from out-of-memory killi ng */ | 441 /** Returns true iff the child process is protected from out-of-memory killi ng */ |
pkotwicz
2016/05/28 01:04:15
Why this change?
Xi Han
2016/05/30 19:59:30
Done.
| |
418 @CalledByNative | 442 @CalledByNative |
419 private static boolean isOomProtected(int pid) { | 443 private static boolean isOomProtected(int pid) { |
420 return sBindingManager.isOomProtected(pid); | 444 return sBindingManager.isOomProtected(pid); |
421 } | 445 } |
422 | 446 |
423 @CalledByNative | 447 @CalledByNative |
424 private static void registerViewSurface(int surfaceId, Surface surface) { | 448 private static void registerViewSurface(int surfaceId, Surface surface) { |
425 if (!surface.isValid()) | 449 if (!surface.isValid()) |
426 throw new RuntimeException("Attempting to register invalid Surface." ); | 450 throw new RuntimeException("Attempting to register invalid Surface." ); |
427 sViewSurfaceMap.put(surfaceId, surface); | 451 sViewSurfaceMap.put(surfaceId, surface); |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
512 } | 536 } |
513 | 537 |
514 /** | 538 /** |
515 * Starts moderate binding management. | 539 * Starts moderate binding management. |
516 * @param context Android's context. | 540 * @param context Android's context. |
517 * @param moderateBindingTillBackgrounded true if the BindingManager should add a moderate | 541 * @param moderateBindingTillBackgrounded true if the BindingManager should add a moderate |
518 * binding to a render process when it is created and remove the moderate bi nding when Chrome is | 542 * binding to a render process when it is created and remove the moderate bi nding when Chrome is |
519 * sent to the background. | 543 * sent to the background. |
520 */ | 544 */ |
521 public static void startModerateBindingManagement( | 545 public static void startModerateBindingManagement( |
522 Context context, boolean moderateBindingTillBackgrounded) { | 546 Context context, boolean moderateBindingTillBackgrounded) { |
pkotwicz
2016/05/28 01:04:15
{@link sBindingManager} is a singleton. This means
Xi Han
2016/05/30 19:59:31
Added a comment here.
| |
523 sBindingManager.startModerateBindingManagement( | 547 sBindingManager.startModerateBindingManagement(context, |
524 context, getNumberOfServices(context, true), moderateBindingTill Backgrounded); | 548 getNumberOfServices(context, true, context.getPackageName()), |
549 moderateBindingTillBackgrounded); | |
525 } | 550 } |
526 | 551 |
527 /** | 552 /** |
528 * Called when the embedding application is brought to foreground. | 553 * Called when the embedding application is brought to foreground. |
529 */ | 554 */ |
530 public static void onBroughtToForeground() { | 555 public static void onBroughtToForeground() { |
531 sApplicationInForeground = true; | 556 sApplicationInForeground = true; |
532 sBindingManager.onBroughtToForeground(); | 557 sBindingManager.onBroughtToForeground(); |
533 } | 558 } |
534 | 559 |
535 /** | 560 /** |
536 * Returns whether the application is currently in the foreground. | 561 * Returns whether the application is currently in the foreground. |
537 */ | 562 */ |
538 static boolean isApplicationInForeground() { | 563 static boolean isApplicationInForeground() { |
539 return sApplicationInForeground; | 564 return sApplicationInForeground; |
540 } | 565 } |
541 | 566 |
542 /** | 567 /** |
543 * Should be called early in startup so the work needed to spawn the child p rocess can be done | 568 * Should be called early in startup so the work needed to spawn the child p rocess can be done |
544 * in parallel to other startup work. Must not be called on the UI thread. S pare connection is | 569 * in parallel to other startup work. Must not be called on the UI thread. S pare connection is |
545 * created in sandboxed child process. | 570 * created in sandboxed child process. |
546 * @param context the application context used for the connection. | 571 * @param context the application context used for the connection. |
547 * @param params child process creation params. | |
548 */ | 572 */ |
549 public static void warmUp(Context context, ChildProcessCreationParams params ) { | 573 public static void warmUp(Context context) { |
550 ChildProcessCreationParams.set(params); | |
551 synchronized (ChildProcessLauncher.class) { | 574 synchronized (ChildProcessLauncher.class) { |
552 assert !ThreadUtils.runningOnUiThread(); | 575 assert !ThreadUtils.runningOnUiThread(); |
553 if (sSpareSandboxedConnection == null) { | 576 if (sSpareSandboxedConnection == null) { |
554 sSpareSandboxedConnection = allocateBoundConnection(context, nul l, true, false); | 577 sSpareSandboxedConnection = allocateBoundConnection(context, nul l, true, false, |
578 ChildProcessCreationParams.get().clone()); | |
555 } | 579 } |
556 } | 580 } |
557 } | 581 } |
558 | 582 |
559 @CalledByNative | 583 @CalledByNative |
560 private static FileDescriptorInfo makeFdInfo( | 584 private static FileDescriptorInfo makeFdInfo( |
561 int id, int fd, boolean autoClose, long offset, long size) { | 585 int id, int fd, boolean autoClose, long offset, long size) { |
562 ParcelFileDescriptor pFd; | 586 ParcelFileDescriptor pFd; |
563 if (autoClose) { | 587 if (autoClose) { |
564 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor. | 588 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor. |
(...skipping 22 matching lines...) Expand all Loading... | |
587 */ | 611 */ |
588 @CalledByNative | 612 @CalledByNative |
589 private static void start(Context context, final String[] commandLine, int c hildProcessId, | 613 private static void start(Context context, final String[] commandLine, int c hildProcessId, |
590 FileDescriptorInfo[] filesToBeMapped, long clientContext) { | 614 FileDescriptorInfo[] filesToBeMapped, long clientContext) { |
591 assert clientContext != 0; | 615 assert clientContext != 0; |
592 | 616 |
593 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; | 617 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; |
594 boolean inSandbox = true; | 618 boolean inSandbox = true; |
595 String processType = | 619 String processType = |
596 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE); | 620 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE); |
621 ChildProcessCreationParams params = ChildProcessCreationParams.get().clo ne(); | |
597 if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { | 622 if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { |
598 callbackType = CALLBACK_FOR_RENDERER_PROCESS; | 623 callbackType = CALLBACK_FOR_RENDERER_PROCESS; |
599 } else if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { | 624 } else if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { |
600 callbackType = CALLBACK_FOR_GPU_PROCESS; | 625 callbackType = CALLBACK_FOR_GPU_PROCESS; |
601 inSandbox = false; | 626 inSandbox = false; |
627 // For GPU process, always set the Chrome's package name. | |
628 params = new ChildProcessCreationParams( | |
629 context.getPackageName(), 0, LibraryProcessType.PROCESS_CHIL D); | |
602 } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType)) { | 630 } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType)) { |
603 // We only support sandboxed right now. | 631 // We only support sandboxed right now. |
604 callbackType = CALLBACK_FOR_UTILITY_PROCESS; | 632 callbackType = CALLBACK_FOR_UTILITY_PROCESS; |
605 } else { | 633 } else { |
606 assert false; | 634 assert false; |
607 } | 635 } |
608 | 636 |
609 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli entContext, | 637 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli entContext, |
610 callbackType, inSandbox); | 638 callbackType, inSandbox, params); |
611 } | 639 } |
612 | 640 |
613 /** | 641 /** |
614 * Spawns a background download process if it hasn't been started. The downl oad process will | 642 * Spawns a background download process if it hasn't been started. The downl oad process will |
615 * manage its own lifecyle and can outlive chrome. | 643 * manage its own lifecyle and can outlive chrome. |
616 * | 644 * |
617 * @param context Context used to obtain the application context. | 645 * @param context Context used to obtain the application context. |
618 * @param commandLine The child process command line argv. | 646 * @param commandLine The child process command line argv. |
619 */ | 647 */ |
620 @SuppressLint("NewApi") | 648 @SuppressLint("NewApi") |
(...skipping 22 matching lines...) Expand all Loading... | |
643 context.startService(intent); | 671 context.startService(intent); |
644 } | 672 } |
645 | 673 |
646 private static void startInternal( | 674 private static void startInternal( |
647 Context context, | 675 Context context, |
648 final String[] commandLine, | 676 final String[] commandLine, |
649 int childProcessId, | 677 int childProcessId, |
650 FileDescriptorInfo[] filesToBeMapped, | 678 FileDescriptorInfo[] filesToBeMapped, |
651 long clientContext, | 679 long clientContext, |
652 int callbackType, | 680 int callbackType, |
653 boolean inSandbox) { | 681 boolean inSandbox, |
682 ChildProcessCreationParams creationParams) { | |
654 try { | 683 try { |
655 TraceEvent.begin("ChildProcessLauncher.startInternal"); | 684 TraceEvent.begin("ChildProcessLauncher.startInternal"); |
656 | 685 |
657 ChildProcessConnection allocatedConnection = null; | 686 ChildProcessConnection allocatedConnection = null; |
658 synchronized (ChildProcessLauncher.class) { | 687 synchronized (ChildProcessLauncher.class) { |
659 if (inSandbox) { | 688 if (inSandbox) { |
660 allocatedConnection = sSpareSandboxedConnection; | 689 allocatedConnection = sSpareSandboxedConnection; |
661 sSpareSandboxedConnection = null; | 690 sSpareSandboxedConnection = null; |
pkotwicz
2016/05/28 01:04:15
We may be wanting to create a connection for a Web
Xi Han
2016/05/30 19:59:30
Add a check here. Only use the SpareSandgoxedConne
| |
662 } | 691 } |
663 } | 692 } |
664 if (allocatedConnection == null) { | 693 if (allocatedConnection == null) { |
665 boolean alwaysInForeground = false; | 694 boolean alwaysInForeground = false; |
666 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true; | 695 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true; |
667 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { | 696 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { |
668 allocatedConnection = allocateBoundConnection( | 697 allocatedConnection = allocateBoundConnection( |
669 context, commandLine, inSandbox, alwaysInForeground) ; | 698 context, commandLine, inSandbox, alwaysInForeground, creationParams); |
670 if (allocatedConnection == null) { | 699 if (allocatedConnection == null) { |
671 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn."); | 700 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn."); |
pkotwicz
2016/05/28 01:04:15
This is suboptimal. There should be a {@link sPend
Xi Han
2016/05/30 19:59:30
Good catch! Make each allocator owns a PendingSpaw
| |
672 sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(co ntext, commandLine, | 701 sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(co ntext, commandLine, |
673 childProcessId, filesToBeMapped, clientContext, | 702 childProcessId, filesToBeMapped, clientContext, |
674 callbackType, inSandbox)); | 703 callbackType, inSandbox)); |
675 return; | 704 return; |
676 } | 705 } |
677 } | 706 } |
678 } | 707 } |
679 | 708 |
680 Log.d(TAG, "Setting up connection to process: slot=%d", | 709 Log.d(TAG, "Setting up connection to process: slot=%d", |
681 allocatedConnection.getServiceNumber()); | 710 allocatedConnection.getServiceNumber()); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
841 } | 870 } |
842 | 871 |
843 static void logPidWarning(int pid, String message) { | 872 static void logPidWarning(int pid, String message) { |
844 // This class is effectively a no-op in single process mode, so don't lo g warnings there. | 873 // This class is effectively a no-op in single process mode, so don't lo g warnings there. |
845 if (pid > 0 && !nativeIsSingleProcess()) { | 874 if (pid > 0 && !nativeIsSingleProcess()) { |
846 Log.w(TAG, "%s, pid=%d", message, pid); | 875 Log.w(TAG, "%s, pid=%d", message, pid); |
847 } | 876 } |
848 } | 877 } |
849 | 878 |
850 @VisibleForTesting | 879 @VisibleForTesting |
851 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext) { | 880 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext, |
852 return allocateBoundConnection(context, null, true, false); | 881 ChildProcessCreationParams creationParams) { |
882 return allocateBoundConnection(context, null, true, false, creationParam s); | |
853 } | 883 } |
854 | 884 |
855 /** | 885 /** |
856 * Queue up a spawn requests for testing. | 886 * Queue up a spawn requests for testing. |
857 */ | 887 */ |
858 @VisibleForTesting | 888 @VisibleForTesting |
859 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine) { | 889 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine) { |
860 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { | 890 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { |
861 sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comma ndLine, 1, | 891 sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comma ndLine, 1, |
862 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true)); | 892 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true)); |
863 } | 893 } |
864 } | 894 } |
865 | 895 |
866 /** @return the count of sandboxed connections managed by the allocator */ | 896 /** |
897 * Returns the number of sandboxed connections of given {@link packageName} managed by the | |
898 * allocator. | |
899 */ | |
867 @VisibleForTesting | 900 @VisibleForTesting |
868 static int allocatedConnectionsCountForTesting(Context context) { | 901 static int allocatedSandboxedConnectionsCountForTesting(Context context, Str ing packageName) { |
869 initConnectionAllocatorsIfNecessary(context); | 902 initConnectionAllocatorsIfNecessary(context, true, packageName); |
870 return sSandboxedChildConnectionAllocator.allocatedConnectionsCountForTe sting(); | 903 return sSandboxedChildConnectionAllocatorMap.get(packageName) |
904 .allocatedConnectionsCountForTesting(); | |
871 } | 905 } |
872 | 906 |
873 /** @return the count of services set up and working */ | 907 /** Returns the count of services set up and working */ |
874 @VisibleForTesting | 908 @VisibleForTesting |
875 static int connectedServicesCountForTesting() { | 909 static int connectedServicesCountForTesting() { |
876 return sServiceMap.size(); | 910 return sServiceMap.size(); |
877 } | 911 } |
878 | 912 |
879 /** @return the count of pending spawns in the queue */ | 913 /** Returns the count of pending spawns in the queue */ |
880 @VisibleForTesting | 914 @VisibleForTesting |
881 static int pendingSpawnsCountForTesting() { | 915 static int pendingSpawnsCountForTesting() { |
882 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { | 916 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { |
883 return sPendingSpawnQueue.sizeLocked(); | 917 return sPendingSpawnQueue.sizeLocked(); |
884 } | 918 } |
885 } | 919 } |
886 | 920 |
887 /** | 921 /** |
888 * Kills the child process for testing. | 922 * Kills the child process for testing. |
889 * @return true iff the process was killed as expected | 923 * @return true iff the process was killed as expected |
890 */ | 924 */ |
891 @VisibleForTesting | 925 @VisibleForTesting |
892 public static boolean crashProcessForTesting(int pid) { | 926 public static boolean crashProcessForTesting(int pid) { |
893 if (sServiceMap.get(pid) == null) return false; | 927 if (sServiceMap.get(pid) == null) return false; |
894 | 928 |
895 try { | 929 try { |
896 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting(); | 930 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting(); |
897 } catch (RemoteException ex) { | 931 } catch (RemoteException ex) { |
898 return false; | 932 return false; |
899 } | 933 } |
900 | 934 |
901 return true; | 935 return true; |
902 } | 936 } |
903 | 937 |
904 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); | 938 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); |
905 private static native void nativeEstablishSurfacePeer( | 939 private static native void nativeEstablishSurfacePeer( |
906 int pid, Surface surface, int primaryID, int secondaryID); | 940 int pid, Surface surface, int primaryID, int secondaryID); |
907 private static native boolean nativeIsSingleProcess(); | 941 private static native boolean nativeIsSingleProcess(); |
908 } | 942 } |
OLD | NEW |