| 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.os.Bundle; | 9 import android.os.Bundle; |
| 10 import android.os.IBinder; | 10 import android.os.IBinder; |
| 11 import android.os.RemoteException; | 11 import android.os.RemoteException; |
| 12 import android.text.TextUtils; | 12 import android.text.TextUtils; |
| 13 | 13 |
| 14 import org.chromium.base.CpuFeatures; | |
| 15 import org.chromium.base.Log; | 14 import org.chromium.base.Log; |
| 16 import org.chromium.base.ThreadUtils; | 15 import org.chromium.base.ThreadUtils; |
| 17 import org.chromium.base.TraceEvent; | 16 import org.chromium.base.TraceEvent; |
| 18 import org.chromium.base.VisibleForTesting; | 17 import org.chromium.base.VisibleForTesting; |
| 19 import org.chromium.base.annotations.SuppressFBWarnings; | 18 import org.chromium.base.annotations.SuppressFBWarnings; |
| 20 import org.chromium.base.library_loader.Linker; | |
| 21 import org.chromium.base.process_launcher.ChildProcessCreationParams; | 19 import org.chromium.base.process_launcher.ChildProcessCreationParams; |
| 22 import org.chromium.base.process_launcher.FileDescriptorInfo; | |
| 23 import org.chromium.content.app.ChromiumLinkerParams; | |
| 24 import org.chromium.content.app.SandboxedProcessService; | 20 import org.chromium.content.app.SandboxedProcessService; |
| 25 import org.chromium.content.common.ContentSwitches; | |
| 26 | 21 |
| 27 import java.util.HashMap; | 22 import java.util.HashMap; |
| 28 import java.util.Map; | 23 import java.util.Map; |
| 29 import java.util.concurrent.ConcurrentHashMap; | 24 import java.util.concurrent.ConcurrentHashMap; |
| 30 | 25 |
| 31 /** | 26 /** |
| 32 * This class provides the method to start/stop ChildProcess called by native. | 27 * This class provides the method to start/stop ChildProcess called by native. |
| 33 * | 28 * |
| 34 * Note about threading. The threading here is complicated and not well document
ed. | 29 * Note about threading. The threading here is complicated and not well document
ed. |
| 35 * Code can run on these threads: UI, Launcher, async thread pool, binder, and o
ne-off | 30 * Code can run on these threads: UI, Launcher, async thread pool, binder, and o
ne-off |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 sSandboxedServiceFactoryForTesting); | 101 sSandboxedServiceFactoryForTesting); |
| 107 } | 102 } |
| 108 sSandboxedChildConnectionAllocatorMap.put(packageName, connectionAll
ocator); | 103 sSandboxedChildConnectionAllocatorMap.put(packageName, connectionAll
ocator); |
| 109 } | 104 } |
| 110 return sSandboxedChildConnectionAllocatorMap.get(packageName); | 105 return sSandboxedChildConnectionAllocatorMap.get(packageName); |
| 111 // TODO(pkotwicz|hanxi): Figure out when old allocators should be remove
d from | 106 // TODO(pkotwicz|hanxi): Figure out when old allocators should be remove
d from |
| 112 // {@code sSandboxedChildConnectionAllocatorMap}. | 107 // {@code sSandboxedChildConnectionAllocatorMap}. |
| 113 } | 108 } |
| 114 | 109 |
| 115 @VisibleForTesting | 110 @VisibleForTesting |
| 116 static ChildProcessConnection allocateConnection( | 111 static ChildProcessConnection allocateConnection(ChildSpawnData spawnData, b
oolean forWarmUp) { |
| 117 ChildSpawnData spawnData, Bundle childProcessCommonParams, boolean f
orWarmUp) { | |
| 118 assert LauncherThread.runningOnLauncherThread(); | 112 assert LauncherThread.runningOnLauncherThread(); |
| 119 ChildProcessConnection.DeathCallback deathCallback = | 113 ChildProcessConnection.DeathCallback deathCallback = |
| 120 new ChildProcessConnection.DeathCallback() { | 114 new ChildProcessConnection.DeathCallback() { |
| 121 @Override | 115 @Override |
| 122 public void onChildProcessDied(ChildProcessConnection connec
tion) { | 116 public void onChildProcessDied(ChildProcessConnection connec
tion) { |
| 123 assert LauncherThread.runningOnLauncherThread(); | 117 assert LauncherThread.runningOnLauncherThread(); |
| 124 if (connection.getPid() != 0) { | 118 if (connection.getPid() != 0) { |
| 125 stop(connection.getPid()); | 119 stop(connection.getPid()); |
| 126 } else { | 120 } else { |
| 127 freeConnection(connection); | 121 freeConnection(connection); |
| 128 } | 122 } |
| 129 } | 123 } |
| 130 }; | 124 }; |
| 131 final ChildProcessCreationParams creationParams = spawnData.getCreationP
arams(); | 125 final ChildProcessCreationParams creationParams = spawnData.getCreationP
arams(); |
| 132 final Context context = spawnData.getContext(); | 126 final Context context = spawnData.getContext(); |
| 133 final boolean inSandbox = spawnData.isInSandbox(); | 127 final boolean inSandbox = spawnData.isInSandbox(); |
| 134 String packageName = | 128 String packageName = |
| 135 creationParams != null ? creationParams.getPackageName() : conte
xt.getPackageName(); | 129 creationParams != null ? creationParams.getPackageName() : conte
xt.getPackageName(); |
| 136 ChildConnectionAllocator allocator = | 130 ChildConnectionAllocator allocator = |
| 137 getConnectionAllocator(context, packageName, inSandbox); | 131 getConnectionAllocator(context, packageName, inSandbox); |
| 138 ChildProcessConnection connection = | 132 ChildProcessConnection connection = |
| 139 allocator.allocate(spawnData, deathCallback, childProcessCommonP
arams, !forWarmUp); | 133 allocator.allocate(spawnData, deathCallback, !forWarmUp); |
| 140 sConnectionsToAllocatorMap.put(connection, allocator); | 134 sConnectionsToAllocatorMap.put(connection, allocator); |
| 141 return connection; | 135 return connection; |
| 142 } | 136 } |
| 143 | 137 |
| 144 private static boolean sLinkerInitialized; | |
| 145 private static long sLinkerLoadAddress; | |
| 146 | |
| 147 private static ChromiumLinkerParams getLinkerParamsForNewConnection() { | |
| 148 if (!sLinkerInitialized) { | |
| 149 if (Linker.isUsed()) { | |
| 150 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress(); | |
| 151 if (sLinkerLoadAddress == 0) { | |
| 152 Log.i(TAG, "Shared RELRO support disabled!"); | |
| 153 } | |
| 154 } | |
| 155 sLinkerInitialized = true; | |
| 156 } | |
| 157 | |
| 158 if (sLinkerLoadAddress == 0) return null; | |
| 159 | |
| 160 // Always wait for the shared RELROs in service processes. | |
| 161 final boolean waitForSharedRelros = true; | |
| 162 if (Linker.areTestsEnabled()) { | |
| 163 Linker linker = Linker.getInstance(); | |
| 164 return new ChromiumLinkerParams(sLinkerLoadAddress, | |
| 165 waitForSharedRelros, | |
| 166 linker.getTestRunnerClassNameForTest
ing(), | |
| 167 linker.getImplementationForTesting()
); | |
| 168 } else { | |
| 169 return new ChromiumLinkerParams(sLinkerLoadAddress, | |
| 170 waitForSharedRelros); | |
| 171 } | |
| 172 } | |
| 173 | |
| 174 @VisibleForTesting | |
| 175 static Bundle createCommonParamsBundle(ChildProcessCreationParams params) { | |
| 176 Bundle commonParams = new Bundle(); | |
| 177 commonParams.putParcelable( | |
| 178 ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNew
Connection()); | |
| 179 final boolean bindToCallerCheck = params == null ? false : params.getBin
dToCallerCheck(); | |
| 180 commonParams.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bind
ToCallerCheck); | |
| 181 return commonParams; | |
| 182 } | |
| 183 | |
| 184 @VisibleForTesting | 138 @VisibleForTesting |
| 185 static ChildProcessConnection allocateBoundConnection(ChildSpawnData spawnDa
ta, | 139 static ChildProcessConnection allocateBoundConnection(ChildSpawnData spawnDa
ta, |
| 186 ChildProcessConnection.StartCallback startCallback, boolean forWarmU
p) { | 140 ChildProcessConnection.StartCallback startCallback, boolean forWarmU
p) { |
| 187 assert LauncherThread.runningOnLauncherThread(); | 141 assert LauncherThread.runningOnLauncherThread(); |
| 188 final Context context = spawnData.getContext(); | 142 final Context context = spawnData.getContext(); |
| 189 final boolean inSandbox = spawnData.isInSandbox(); | 143 final boolean inSandbox = spawnData.isInSandbox(); |
| 190 final ChildProcessCreationParams creationParams = spawnData.getCreationP
arams(); | 144 final ChildProcessCreationParams creationParams = spawnData.getCreationP
arams(); |
| 191 | 145 |
| 192 ChildProcessConnection connection = allocateConnection( | 146 ChildProcessConnection connection = allocateConnection(spawnData, forWar
mUp); |
| 193 spawnData, createCommonParamsBundle(spawnData.getCreationParams(
)), forWarmUp); | |
| 194 if (connection != null) { | 147 if (connection != null) { |
| 195 // Non sandboxed processes are privileged processes that should be s
trongly bound. | 148 // Non sandboxed processes are privileged processes that should be s
trongly bound. |
| 196 boolean useStrongBinding = !inSandbox; | 149 boolean useStrongBinding = !inSandbox; |
| 197 connection.start(useStrongBinding, startCallback); | 150 connection.start(useStrongBinding, startCallback); |
| 198 | 151 |
| 199 String packageName = creationParams != null ? creationParams.getPack
ageName() | 152 String packageName = creationParams != null ? creationParams.getPack
ageName() |
| 200 : context.getPackageName
(); | 153 : context.getPackageName
(); |
| 201 if (inSandbox | 154 if (inSandbox |
| 202 && !getConnectionAllocator(context, packageName, true /* san
dboxed */) | 155 && !getConnectionAllocator(context, packageName, true /* san
dboxed */) |
| 203 .isFreeConnectionAvailable()) { | 156 .isFreeConnectionAvailable()) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 225 LauncherThread.postDelayed(new Runnable() { | 178 LauncherThread.postDelayed(new Runnable() { |
| 226 @Override | 179 @Override |
| 227 public void run() { | 180 public void run() { |
| 228 ChildConnectionAllocator allocator = sConnectionsToAllocatorMap.
remove(conn); | 181 ChildConnectionAllocator allocator = sConnectionsToAllocatorMap.
remove(conn); |
| 229 assert allocator != null; | 182 assert allocator != null; |
| 230 final ChildSpawnData pendingSpawn = allocator.free(conn); | 183 final ChildSpawnData pendingSpawn = allocator.free(conn); |
| 231 if (pendingSpawn != null) { | 184 if (pendingSpawn != null) { |
| 232 LauncherThread.post(new Runnable() { | 185 LauncherThread.post(new Runnable() { |
| 233 @Override | 186 @Override |
| 234 public void run() { | 187 public void run() { |
| 235 startInternal(pendingSpawn.getContext(), pendingSpaw
n.getCommandLine(), | 188 start(pendingSpawn.getContext(), pendingSpawn.getSer
viceBundle(), |
| 236 pendingSpawn.getFilesToBeMapped(), | 189 pendingSpawn.getConnectionBundle(), |
| 237 pendingSpawn.getLaunchCallback(), | 190 pendingSpawn.getLaunchCallback(), |
| 238 pendingSpawn.getChildProcessCallback(), | 191 pendingSpawn.getChildProcessCallback(), |
| 239 pendingSpawn.isInSandbox(), pendingSpawn.isA
lwaysInForeground(), | 192 pendingSpawn.isInSandbox(), pendingSpawn.isA
lwaysInForeground(), |
| 240 pendingSpawn.getCreationParams()); | 193 pendingSpawn.getCreationParams()); |
| 241 } | 194 } |
| 242 }); | 195 }); |
| 243 } | 196 } |
| 244 } | 197 } |
| 245 }, FREE_CONNECTION_DELAY_MILLIS); | 198 }, FREE_CONNECTION_DELAY_MILLIS); |
| 246 } | 199 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 @Override | 324 @Override |
| 372 public void onChildStartFailed() { | 325 public void onChildStartFailed() { |
| 373 assert LauncherThread.runningOnLauncherThread(); | 326 assert LauncherThread.runningOnLauncherThread(); |
| 374 Log.e(TAG, "Failed to warm up the spare sandbox
service"); | 327 Log.e(TAG, "Failed to warm up the spare sandbox
service"); |
| 375 if (sSpareConnectionStartCallback != null) { | 328 if (sSpareConnectionStartCallback != null) { |
| 376 sSpareConnectionStartCallback.onChildStartFa
iled(); | 329 sSpareConnectionStartCallback.onChildStartFa
iled(); |
| 377 } | 330 } |
| 378 clearSpareConnection(); | 331 clearSpareConnection(); |
| 379 } | 332 } |
| 380 }; | 333 }; |
| 381 ChildSpawnData spawnData = new ChildSpawnData(context, null /* c
ommandLine */, | 334 boolean bindToCallerCheck = params == null ? false : params.getB
indToCallerCheck(); |
| 382 null /* filesToBeMapped */, null /* launchCallback */, | 335 ChildSpawnData spawnData = new ChildSpawnData(context, |
| 336 ChildProcessLauncherHelper.createServiceBundle(bindToCal
lerCheck), |
| 337 null /* connectionBundle */, null /* launchCallback */, |
| 383 null /* child process callback */, true /* inSandbox */, | 338 null /* child process callback */, true /* inSandbox */, |
| 384 SPARE_CONNECTION_ALWAYS_IN_FOREGROUND, params); | 339 SPARE_CONNECTION_ALWAYS_IN_FOREGROUND, params); |
| 385 sSpareSandboxedConnection = | 340 sSpareSandboxedConnection = |
| 386 allocateBoundConnection(spawnData, startCallback, true /
* forWarmUp */); | 341 allocateBoundConnection(spawnData, startCallback, true /
* forWarmUp */); |
| 387 sSpareConnectionStarting = sSpareSandboxedConnection != null; | 342 sSpareConnectionStarting = sSpareSandboxedConnection != null; |
| 388 } | 343 } |
| 389 }); | 344 }); |
| 390 } | 345 } |
| 391 | 346 |
| 392 private static void clearSpareConnection() { | 347 private static void clearSpareConnection() { |
| 393 assert LauncherThread.runningOnLauncherThread(); | 348 assert LauncherThread.runningOnLauncherThread(); |
| 394 sSpareSandboxedConnection = null; | 349 sSpareSandboxedConnection = null; |
| 395 sSpareConnectionStarting = false; | 350 sSpareConnectionStarting = false; |
| 396 sSpareConnectionStartCallback = null; | 351 sSpareConnectionStartCallback = null; |
| 397 } | 352 } |
| 398 | 353 |
| 399 /** | 354 /** |
| 400 * Spawns and connects to a child process. It will not block, but will inste
ad callback to | 355 * Spawns and connects to a child process. It will not block, but will inste
ad callback to |
| 401 * {@link #LaunchCallback} on the launcher thread when the connection is est
ablished on. | 356 * {@link #LaunchCallback} on the launcher thread when the connection is est
ablished on. |
| 402 * | 357 * |
| 403 * @param context Context used to obtain the application context. | 358 * @param context Context used to obtain the application context. |
| 404 * @param paramId Key used to retrieve ChildProcessCreationParams. | 359 * @param paramId Key used to retrieve ChildProcessCreationParams. |
| 405 * @param commandLine The child process command line argv. | 360 * @param serviceBundle The Bundle passed in the intent used to bind to the
service. |
| 406 * @param filesToBeMapped File IDs, FDs, offsets, and lengths to pass throug
h. | 361 * @param connectionBundle The Bundle passed in setupConnection call. |
| 407 * @param launchCallback Callback invoked when the connection is established
. | 362 * @param launchCallback Callback invoked when the connection is established
. |
| 363 * @param childProcessCallback IBinder callback passed to the service. |
| 408 */ | 364 */ |
| 409 static void start(Context context, int paramId, final String[] commandLine, | |
| 410 FileDescriptorInfo[] filesToBeMapped, LaunchCallback launchCallback)
{ | |
| 411 assert LauncherThread.runningOnLauncherThread(); | |
| 412 IBinder childProcessCallback = null; | |
| 413 boolean inSandbox = true; | |
| 414 boolean alwaysInForeground = false; | |
| 415 String processType = | |
| 416 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT
CH_PROCESS_TYPE); | |
| 417 ChildProcessCreationParams params = ChildProcessCreationParams.get(param
Id); | |
| 418 if (paramId != ChildProcessCreationParams.DEFAULT_ID && params == null)
{ | |
| 419 throw new RuntimeException("CreationParams id " + paramId + " not fo
und"); | |
| 420 } | |
| 421 if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { | |
| 422 if (params != null && !params.getPackageName().equals(context.getPac
kageName())) { | |
| 423 // WebViews and WebAPKs have renderer processes running in their
applications. | |
| 424 // When launching these renderer processes, {@link ChildProcessC
onnection} | |
| 425 // requires the package name of the application which holds the
renderer process. | |
| 426 // Therefore, the package name in ChildProcessCreationParams cou
ld be the package | |
| 427 // name of WebViews, WebAPKs, or Chrome, depending on the host a
pplication. | |
| 428 // Except renderer process, all other child processes should use
Chrome's package | |
| 429 // name. In WebAPK, ChildProcessCreationParams are initialized w
ith WebAPK's | |
| 430 // package name. Make a copy of the WebAPK's params, but replace
the package with | |
| 431 // Chrome's package to use when initializing a non-renderer proc
esses. | |
| 432 // TODO(boliu): Should fold into |paramId|. Investigate why this
is needed. | |
| 433 params = new ChildProcessCreationParams(context.getPackageName()
, | |
| 434 params.getIsExternalService(), params.getLibraryProcessT
ype(), | |
| 435 params.getBindToCallerCheck()); | |
| 436 } | |
| 437 if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { | |
| 438 childProcessCallback = new GpuProcessCallback(); | |
| 439 inSandbox = false; | |
| 440 alwaysInForeground = true; | |
| 441 } else { | |
| 442 // We only support sandboxed utility processes now. | |
| 443 assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType
); | |
| 444 } | |
| 445 } | |
| 446 | |
| 447 startInternal(context, commandLine, filesToBeMapped, launchCallback, chi
ldProcessCallback, | |
| 448 inSandbox, alwaysInForeground, params); | |
| 449 } | |
| 450 | |
| 451 @VisibleForTesting | 365 @VisibleForTesting |
| 452 public static ChildProcessConnection startInternal(final Context context, | 366 public static boolean start(final Context context, final Bundle serviceBundl
e, |
| 453 final String[] commandLine, final FileDescriptorInfo[] filesToBeMapp
ed, | 367 final Bundle connectionBundle, final LaunchCallback launchCallback, |
| 454 final LaunchCallback launchCallback, final IBinder childProcessCallb
ack, | 368 final IBinder childProcessCallback, final boolean inSandbox, |
| 455 final boolean inSandbox, final boolean alwaysInForeground, | 369 final boolean alwaysInForeground, final ChildProcessCreationParams c
reationParams) { |
| 456 final ChildProcessCreationParams creationParams) { | |
| 457 assert LauncherThread.runningOnLauncherThread(); | 370 assert LauncherThread.runningOnLauncherThread(); |
| 458 try { | 371 try { |
| 459 TraceEvent.begin("ChildProcessLauncher.startInternal"); | 372 TraceEvent.begin("ChildProcessLauncher.start"); |
| 460 | 373 |
| 461 ChildProcessConnection allocatedConnection = null; | 374 ChildProcessConnection allocatedConnection = null; |
| 462 String packageName = creationParams != null ? creationParams.getPack
ageName() | 375 String packageName = creationParams != null ? creationParams.getPack
ageName() |
| 463 : context.getPackageName(); | 376 : context.getPackageName(); |
| 464 ChildProcessConnection.StartCallback startCallback = | 377 ChildProcessConnection.StartCallback startCallback = |
| 465 new ChildProcessConnection.StartCallback() { | 378 new ChildProcessConnection.StartCallback() { |
| 466 @Override | 379 @Override |
| 467 public void onChildStarted() {} | 380 public void onChildStarted() {} |
| 468 | 381 |
| 469 @Override | 382 @Override |
| 470 public void onChildStartFailed() { | 383 public void onChildStartFailed() { |
| 471 assert LauncherThread.runningOnLauncherThread(); | 384 assert LauncherThread.runningOnLauncherThread(); |
| 472 Log.e(TAG, "ChildProcessConnection.start failed, try
ing again"); | 385 Log.e(TAG, "ChildProcessConnection.start failed, try
ing again"); |
| 473 LauncherThread.post(new Runnable() { | 386 LauncherThread.post(new Runnable() { |
| 474 @Override | 387 @Override |
| 475 public void run() { | 388 public void run() { |
| 476 // The child process may already be bound to
another client | 389 // The child process may already be bound to
another client |
| 477 // (this can happen if multi-process WebView
is used in more | 390 // (this can happen if multi-process WebView
is used in more |
| 478 // than one process), so try starting the pr
ocess again. | 391 // than one process), so try starting the pr
ocess again. |
| 479 // This connection that failed to start has
not been freed, | 392 // This connection that failed to start has
not been freed, |
| 480 // so a new bound connection will be allocat
ed. | 393 // so a new bound connection will be allocat
ed. |
| 481 startInternal(context, commandLine, filesToB
eMapped, | 394 start(context, serviceBundle, connectionBund
le, launchCallback, |
| 482 launchCallback, childProcessCallback
, inSandbox, | 395 childProcessCallback, inSandbox, alw
aysInForeground, |
| 483 alwaysInForeground, creationParams); | 396 creationParams); |
| 484 } | 397 } |
| 485 }); | 398 }); |
| 486 } | 399 } |
| 487 }; | 400 }; |
| 488 | 401 |
| 489 if (inSandbox && sSpareSandboxedConnection != null | 402 if (inSandbox && sSpareSandboxedConnection != null |
| 490 && sSpareConnectionStartCallback == null | 403 && sSpareConnectionStartCallback == null |
| 491 && SPARE_CONNECTION_ALWAYS_IN_FOREGROUND == alwaysInForegrou
nd | 404 && SPARE_CONNECTION_ALWAYS_IN_FOREGROUND == alwaysInForegrou
nd |
| 492 && sSpareSandboxedConnection.getPackageName().equals(package
Name) | 405 && sSpareSandboxedConnection.getPackageName().equals(package
Name) |
| 493 // Object identity check for getDefault should be enough. Th
e default is | 406 // Object identity check for getDefault should be enough. Th
e default is |
| 494 // not supposed to change once set. | 407 // not supposed to change once set. |
| 495 && creationParams == ChildProcessCreationParams.getDefault()
) { | 408 && creationParams == ChildProcessCreationParams.getDefault()
) { |
| 496 allocatedConnection = sSpareSandboxedConnection; | 409 allocatedConnection = sSpareSandboxedConnection; |
| 497 if (sSpareConnectionStarting) { | 410 if (sSpareConnectionStarting) { |
| 498 sSpareConnectionStartCallback = startCallback; | 411 sSpareConnectionStartCallback = startCallback; |
| 499 } else { | 412 } else { |
| 500 clearSpareConnection(); | 413 clearSpareConnection(); |
| 501 } | 414 } |
| 502 } | 415 } |
| 503 if (allocatedConnection == null) { | 416 if (allocatedConnection == null) { |
| 504 ChildSpawnData spawnData = new ChildSpawnData(context, commandLi
ne, filesToBeMapped, | 417 ChildSpawnData spawnData = new ChildSpawnData(context, serviceBu
ndle, |
| 505 launchCallback, childProcessCallback, inSandbox, alwaysI
nForeground, | 418 connectionBundle, launchCallback, childProcessCallback,
inSandbox, |
| 506 creationParams); | 419 alwaysInForeground, creationParams); |
| 507 allocatedConnection = | 420 allocatedConnection = |
| 508 allocateBoundConnection(spawnData, startCallback, false
/* forWarmUp */); | 421 allocateBoundConnection(spawnData, startCallback, false
/* forWarmUp */); |
| 509 if (allocatedConnection == null) { | 422 if (allocatedConnection == null) { |
| 510 return null; | 423 return false; |
| 511 } | 424 } |
| 512 } | 425 } |
| 513 | |
| 514 boolean addToBindingmanager = inSandbox; | 426 boolean addToBindingmanager = inSandbox; |
| 515 triggerConnectionSetup(allocatedConnection, commandLine, filesToBeMa
pped, | 427 triggerConnectionSetup(allocatedConnection, connectionBundle, childP
rocessCallback, |
| 516 childProcessCallback, launchCallback, addToBindingmanager); | 428 launchCallback, addToBindingmanager); |
| 517 return allocatedConnection; | 429 return true; |
| 518 } finally { | 430 } finally { |
| 519 TraceEvent.end("ChildProcessLauncher.startInternal"); | 431 TraceEvent.end("ChildProcessLauncher.start"); |
| 520 } | 432 } |
| 521 } | 433 } |
| 522 | 434 |
| 523 /** | |
| 524 * Create the common bundle to be passed to child processes. | |
| 525 * @param context Application context. | |
| 526 * @param commandLine Command line params to be passed to the service. | |
| 527 * @param linkerParams Linker params to start the service. | |
| 528 */ | |
| 529 protected static Bundle createsServiceBundle( | |
| 530 String[] commandLine, FileDescriptorInfo[] filesToBeMapped) { | |
| 531 Bundle bundle = new Bundle(); | |
| 532 bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, commandL
ine); | |
| 533 bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, filesToBeMa
pped); | |
| 534 bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCoun
t()); | |
| 535 bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.get
Mask()); | |
| 536 bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS, Linker.getInstance()
.getSharedRelros()); | |
| 537 return bundle; | |
| 538 } | |
| 539 | |
| 540 @VisibleForTesting | 435 @VisibleForTesting |
| 541 static void triggerConnectionSetup(final ChildProcessConnection connection, | 436 static void triggerConnectionSetup(final ChildProcessConnection connection, |
| 542 String[] commandLine, FileDescriptorInfo[] filesToBeMapped, | 437 Bundle connectionBundle, final IBinder childProcessCallback, |
| 543 final IBinder childProcessCallback, final LaunchCallback launchCallb
ack, | 438 final LaunchCallback launchCallback, final boolean addToBindingmanag
er) { |
| 544 final boolean addToBindingmanager) { | |
| 545 assert LauncherThread.runningOnLauncherThread(); | 439 assert LauncherThread.runningOnLauncherThread(); |
| 546 Log.d(TAG, "Setting up connection to process, connection name=%s", | 440 Log.d(TAG, "Setting up connection to process, connection name=%s", |
| 547 connection.getServiceName()); | 441 connection.getServiceName()); |
| 548 ChildProcessConnection.ConnectionCallback connectionCallback = | 442 ChildProcessConnection.ConnectionCallback connectionCallback = |
| 549 new ChildProcessConnection.ConnectionCallback() { | 443 new ChildProcessConnection.ConnectionCallback() { |
| 550 @Override | 444 @Override |
| 551 public void onConnected(ChildProcessConnection connection) { | 445 public void onConnected(ChildProcessConnection connection) { |
| 552 assert LauncherThread.runningOnLauncherThread(); | 446 assert LauncherThread.runningOnLauncherThread(); |
| 553 if (connection != null) { | 447 if (connection != null) { |
| 554 int pid = connection.getPid(); | 448 int pid = connection.getPid(); |
| 555 Log.d(TAG, "on connect callback, pid=%d", pid); | 449 Log.d(TAG, "on connect callback, pid=%d", pid); |
| 556 if (addToBindingmanager) { | 450 if (addToBindingmanager) { |
| 557 getBindingManager().addNewConnection(pid, connec
tion); | 451 getBindingManager().addNewConnection(pid, connec
tion); |
| 558 } | 452 } |
| 559 sServiceMap.put(pid, connection); | 453 sServiceMap.put(pid, connection); |
| 560 } | 454 } |
| 561 // If the connection fails and pid == 0, the Java-side c
leanup was already | 455 // If the connection fails and pid == 0, the Java-side c
leanup was already |
| 562 // handled by DeathCallback. We still have to call back
to native for | 456 // handled by DeathCallback. We still have to call back
to native for |
| 563 // cleanup there. | 457 // cleanup there. |
| 564 if (launchCallback != null) { // Will be null in Java in
strumentation tests. | 458 if (launchCallback != null) { // Will be null in Java in
strumentation tests. |
| 565 launchCallback.onChildProcessStarted(connection); | 459 launchCallback.onChildProcessStarted(connection); |
| 566 } | 460 } |
| 567 } | 461 } |
| 568 }; | 462 }; |
| 569 | 463 |
| 570 connection.setupConnection( | 464 connection.setupConnection(connectionBundle, childProcessCallback, conne
ctionCallback); |
| 571 commandLine, filesToBeMapped, childProcessCallback, connectionCa
llback); | |
| 572 } | 465 } |
| 573 | 466 |
| 574 /** | 467 /** |
| 575 * Terminates a child process. This may be called from any thread. | 468 * Terminates a child process. This may be called from any thread. |
| 576 * | 469 * |
| 577 * @param pid The pid (process handle) of the service connection obtained fr
om {@link #start}. | 470 * @param pid The pid (process handle) of the service connection obtained fr
om {@link #start}. |
| 578 */ | 471 */ |
| 579 static void stop(int pid) { | 472 static void stop(int pid) { |
| 580 assert LauncherThread.runningOnLauncherThread(); | 473 assert LauncherThread.runningOnLauncherThread(); |
| 581 Log.d(TAG, "stopping child connection: pid=%d", pid); | 474 Log.d(TAG, "stopping child connection: pid=%d", pid); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 | 516 |
| 624 try { | 517 try { |
| 625 sServiceMap.get(pid).crashServiceForTesting(); | 518 sServiceMap.get(pid).crashServiceForTesting(); |
| 626 } catch (RemoteException ex) { | 519 } catch (RemoteException ex) { |
| 627 return false; | 520 return false; |
| 628 } | 521 } |
| 629 | 522 |
| 630 return true; | 523 return true; |
| 631 } | 524 } |
| 632 } | 525 } |
| OLD | NEW |