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.os.Bundle; | 8 import android.os.Bundle; |
9 import android.os.IBinder; | 9 import android.os.IBinder; |
10 import android.os.RemoteException; | 10 import android.os.RemoteException; |
(...skipping 18 matching lines...) Expand all Loading... |
29 * 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. |
30 * 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 |
31 * background threads. | 31 * background threads. |
32 */ | 32 */ |
33 public class ChildProcessLauncher { | 33 public class ChildProcessLauncher { |
34 private static final String TAG = "ChildProcLauncher"; | 34 private static final String TAG = "ChildProcLauncher"; |
35 | 35 |
36 /** | 36 /** |
37 * Implemented by ChildProcessLauncherHelper. | 37 * Implemented by ChildProcessLauncherHelper. |
38 */ | 38 */ |
39 public interface LaunchCallback { void onChildProcessStarted(int pid); } | 39 public interface LaunchCallback { |
| 40 void onChildProcessStarted(BaseChildProcessConnection connection); |
| 41 } |
40 | 42 |
41 private static final boolean SPARE_CONNECTION_ALWAYS_IN_FOREGROUND = false; | 43 private static final boolean SPARE_CONNECTION_ALWAYS_IN_FOREGROUND = false; |
42 | 44 |
43 @VisibleForTesting | 45 @VisibleForTesting |
44 static ChildProcessConnection allocateConnection( | 46 static BaseChildProcessConnection allocateConnection( |
45 ChildSpawnData spawnData, Bundle childProcessCommonParams, boolean f
orWarmUp) { | 47 ChildSpawnData spawnData, Bundle childProcessCommonParams, boolean f
orWarmUp) { |
46 assert LauncherThread.runningOnLauncherThread(); | 48 assert LauncherThread.runningOnLauncherThread(); |
47 ChildProcessConnection.DeathCallback deathCallback = | 49 BaseChildProcessConnection.DeathCallback deathCallback = |
48 new ChildProcessConnection.DeathCallback() { | 50 new BaseChildProcessConnection.DeathCallback() { |
49 @Override | 51 @Override |
50 public void onChildProcessDied(ChildProcessConnection connec
tion) { | 52 public void onChildProcessDied(BaseChildProcessConnection co
nnection) { |
51 assert LauncherThread.runningOnLauncherThread(); | 53 assert LauncherThread.runningOnLauncherThread(); |
52 if (connection.getPid() != 0) { | 54 if (connection.getPid() != 0) { |
53 stop(connection.getPid()); | 55 stop(connection.getPid()); |
54 } else { | 56 } else { |
55 freeConnection(connection); | 57 freeConnection(connection); |
56 } | 58 } |
57 } | 59 } |
58 }; | 60 }; |
59 final ChildProcessCreationParams creationParams = spawnData.getCreationP
arams(); | 61 final ChildProcessCreationParams creationParams = spawnData.getCreationP
arams(); |
60 final Context context = spawnData.getContext(); | 62 final Context context = spawnData.getContext(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 static Bundle createCommonParamsBundle(ChildProcessCreationParams params) { | 101 static Bundle createCommonParamsBundle(ChildProcessCreationParams params) { |
100 Bundle commonParams = new Bundle(); | 102 Bundle commonParams = new Bundle(); |
101 commonParams.putParcelable( | 103 commonParams.putParcelable( |
102 ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNew
Connection()); | 104 ChildProcessConstants.EXTRA_LINKER_PARAMS, getLinkerParamsForNew
Connection()); |
103 final boolean bindToCallerCheck = params == null ? false : params.getBin
dToCallerCheck(); | 105 final boolean bindToCallerCheck = params == null ? false : params.getBin
dToCallerCheck(); |
104 commonParams.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bind
ToCallerCheck); | 106 commonParams.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bind
ToCallerCheck); |
105 return commonParams; | 107 return commonParams; |
106 } | 108 } |
107 | 109 |
108 @VisibleForTesting | 110 @VisibleForTesting |
109 static ChildProcessConnection allocateBoundConnection(ChildSpawnData spawnDa
ta, | 111 static BaseChildProcessConnection allocateBoundConnection(ChildSpawnData spa
wnData, |
110 ChildProcessConnection.StartCallback startCallback, boolean forWarmU
p) { | 112 BaseChildProcessConnection.StartCallback startCallback, boolean forW
armUp) { |
111 assert LauncherThread.runningOnLauncherThread(); | 113 assert LauncherThread.runningOnLauncherThread(); |
112 final Context context = spawnData.getContext(); | 114 final Context context = spawnData.getContext(); |
113 final boolean inSandbox = spawnData.isInSandbox(); | 115 final boolean inSandbox = spawnData.isInSandbox(); |
114 final ChildProcessCreationParams creationParams = spawnData.getCreationP
arams(); | 116 final ChildProcessCreationParams creationParams = spawnData.getCreationP
arams(); |
115 | 117 |
116 ChildProcessConnection connection = allocateConnection( | 118 BaseChildProcessConnection connection = allocateConnection( |
117 spawnData, createCommonParamsBundle(spawnData.getCreationParams(
)), forWarmUp); | 119 spawnData, createCommonParamsBundle(spawnData.getCreationParams(
)), forWarmUp); |
118 if (connection != null) { | 120 if (connection != null) { |
119 connection.start(startCallback); | 121 connection.start(startCallback); |
120 | 122 |
121 String packageName = creationParams != null ? creationParams.getPack
ageName() | 123 String packageName = creationParams != null ? creationParams.getPack
ageName() |
122 : context.getPackageName
(); | 124 : context.getPackageName
(); |
123 if (inSandbox | 125 if (inSandbox |
124 && !ChildConnectionAllocator.getAllocator(context, packageNa
me, inSandbox) | 126 && !ChildConnectionAllocator |
| 127 .getAllocator(context, packageName, true /* sand
boxed */) |
125 .isFreeConnectionAvailable()) { | 128 .isFreeConnectionAvailable()) { |
126 // Proactively releases all the moderate bindings once all the s
andboxed services | 129 // Proactively releases all the moderate bindings once all the s
andboxed services |
127 // are allocated, which will be very likely to have some of them
killed by OOM | 130 // are allocated, which will be very likely to have some of them
killed by OOM |
128 // killer. | 131 // killer. |
129 getBindingManager().releaseAllModerateBindings(); | 132 getBindingManager().releaseAllModerateBindings(); |
130 } | 133 } |
131 } | 134 } |
132 return connection; | 135 return connection; |
133 } | 136 } |
134 | 137 |
135 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; | 138 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; |
136 | 139 |
137 private static void freeConnection(ChildProcessConnection connection) { | 140 private static void freeConnection(BaseChildProcessConnection connection) { |
138 assert LauncherThread.runningOnLauncherThread(); | 141 assert LauncherThread.runningOnLauncherThread(); |
139 if (connection == sSpareSandboxedConnection) clearSpareConnection(); | 142 if (connection == sSpareSandboxedConnection) clearSpareConnection(); |
140 | 143 |
141 // Freeing a service should be delayed. This is so that we avoid immedia
tely reusing the | 144 // Freeing a service should be delayed. This is so that we avoid immedia
tely reusing the |
142 // freed service (see http://crbug.com/164069): the framework might keep
a service process | 145 // freed service (see http://crbug.com/164069): the framework might keep
a service process |
143 // alive when it's been unbound for a short time. If a new connection to
the same service | 146 // alive when it's been unbound for a short time. If a new connection to
the same service |
144 // is bound at that point, the process is reused and bad things happen (
mostly static | 147 // is bound at that point, the process is reused and bad things happen (
mostly static |
145 // variables are set when we don't expect them to). | 148 // variables are set when we don't expect them to). |
146 final ChildProcessConnection conn = connection; | 149 final BaseChildProcessConnection conn = connection; |
147 LauncherThread.postDelayed(new Runnable() { | 150 LauncherThread.postDelayed(new Runnable() { |
148 @Override | 151 @Override |
149 public void run() { | 152 public void run() { |
150 // TODO(jcivelli): it should be safe to pass a null Context here
as it is used to | 153 // TODO(jcivelli): it should be safe to pass a null Context here
as it is used to |
151 // initialize the ChildConnectionAllocator object and if we are
freeing a | 154 // initialize the ChildConnectionAllocator object and if we are
freeing a |
152 // connection, we must have allocated one previously guaranteein
g it is already | 155 // connection, we must have allocated one previously guaranteein
g it is already |
153 // initialized. When we consolidate ChildProcessLauncher and | 156 // initialized. When we consolidate ChildProcessLauncher and |
154 // ChildProcessLauncherHelper, we'll have a context around that
we can pass in | 157 // ChildProcessLauncherHelper, we'll have a context around that
we can pass in |
155 // there. | 158 // there. |
156 ChildConnectionAllocator allocator = ChildConnectionAllocator.ge
tAllocator( | 159 ChildConnectionAllocator allocator = ChildConnectionAllocator.ge
tAllocator( |
157 null /* context */, conn.getPackageName(), conn.isInSand
box()); | 160 null /* context */, conn.getPackageName(), conn.isSandbo
xed()); |
158 assert allocator != null; | 161 assert allocator != null; |
159 final ChildSpawnData pendingSpawn = allocator.free(conn); | 162 final ChildSpawnData pendingSpawn = allocator.free(conn); |
160 if (pendingSpawn != null) { | 163 if (pendingSpawn != null) { |
161 LauncherThread.post(new Runnable() { | 164 LauncherThread.post(new Runnable() { |
162 @Override | 165 @Override |
163 public void run() { | 166 public void run() { |
164 startInternal(pendingSpawn.getContext(), pendingSpaw
n.getCommandLine(), | 167 startInternal(pendingSpawn.getContext(), pendingSpaw
n.getCommandLine(), |
165 pendingSpawn.getChildProcessId(), | 168 pendingSpawn.getChildProcessId(), |
166 pendingSpawn.getFilesToBeMapped(), | 169 pendingSpawn.getFilesToBeMapped(), |
167 pendingSpawn.getLaunchCallback(), | 170 pendingSpawn.getLaunchCallback(), |
168 pendingSpawn.getChildProcessCallback(), | 171 pendingSpawn.getChildProcessCallback(), |
169 pendingSpawn.isInSandbox(), pendingSpawn.isA
lwaysInForeground(), | 172 pendingSpawn.isInSandbox(), pendingSpawn.isA
lwaysInForeground(), |
170 pendingSpawn.getCreationParams()); | 173 pendingSpawn.getCreationParams()); |
171 } | 174 } |
172 }); | 175 }); |
173 } | 176 } |
174 } | 177 } |
175 }, FREE_CONNECTION_DELAY_MILLIS); | 178 }, FREE_CONNECTION_DELAY_MILLIS); |
176 } | 179 } |
177 | 180 |
178 // Represents an invalid process handle; same as base/process/process.h kNul
lProcessHandle. | |
179 private static final int NULL_PROCESS_HANDLE = 0; | |
180 | |
181 // Map from pid to ChildService connection. | 181 // Map from pid to ChildService connection. |
182 private static Map<Integer, ChildProcessConnection> sServiceMap = | 182 private static Map<Integer, BaseChildProcessConnection> sServiceMap = |
183 new ConcurrentHashMap<Integer, ChildProcessConnection>(); | 183 new ConcurrentHashMap<Integer, BaseChildProcessConnection>(); |
184 | 184 |
185 // Lock for getBindingManager() | 185 // Lock for getBindingManager() |
186 private static final Object sBindingManagerLock = new Object(); | 186 private static final Object sBindingManagerLock = new Object(); |
187 | 187 |
188 // These variables are used for the warm up sandboxed connection. | 188 // These variables are used for the warm up sandboxed connection. |
189 // |sSpareSandboxedConnection| is non-null when there is a pending connectio
n. Note it's cleared | 189 // |sSpareSandboxedConnection| is non-null when there is a pending connectio
n. Note it's cleared |
190 // to null again after the connection is used for a real child process. | 190 // to null again after the connection is used for a real child process. |
191 // |sSpareConnectionStarting| is true if ChildProcessConnection.StartCallbac
k has not fired. | 191 // |sSpareConnectionStarting| is true if ChildProcessConnection.StartCallbac
k has not fired. |
192 // This is used for a child process allocation to determine if StartCallback
should be chained. | 192 // This is used for a child process allocation to determine if StartCallback
should be chained. |
193 // |sSpareConnectionStartCallback| is the chained StartCallback. This is als
o used to determine | 193 // |sSpareConnectionStartCallback| is the chained StartCallback. This is als
o used to determine |
194 // if there is already a child process launch that's used this this connecti
on. | 194 // if there is already a child process launch that's used this this connecti
on. |
195 private static ChildProcessConnection sSpareSandboxedConnection; | 195 private static BaseChildProcessConnection sSpareSandboxedConnection; |
196 private static boolean sSpareConnectionStarting; | 196 private static boolean sSpareConnectionStarting; |
197 private static ChildProcessConnection.StartCallback sSpareConnectionStartCal
lback; | 197 private static BaseChildProcessConnection.StartCallback sSpareConnectionStar
tCallback; |
198 | 198 |
199 // Manages oom bindings used to bind chind services. Lazily initialized by g
etBindingManager() | 199 // Manages oom bindings used to bind chind services. Lazily initialized by g
etBindingManager() |
200 private static BindingManager sBindingManager; | 200 private static BindingManager sBindingManager; |
201 | 201 |
202 // Whether the main application is currently brought to the foreground. | 202 // Whether the main application is currently brought to the foreground. |
203 private static boolean sApplicationInForeground = true; | 203 private static boolean sApplicationInForeground = true; |
204 | 204 |
205 // Lazy initialize sBindingManager | 205 // Lazy initialize sBindingManager |
206 // TODO(boliu): This should be internal to content. | 206 // TODO(boliu): This should be internal to content. |
207 public static BindingManager getBindingManager() { | 207 public static BindingManager getBindingManager() { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 * @param context the application context used for the connection. | 271 * @param context the application context used for the connection. |
272 */ | 272 */ |
273 public static void warmUp(final Context context) { | 273 public static void warmUp(final Context context) { |
274 assert ThreadUtils.runningOnUiThread(); | 274 assert ThreadUtils.runningOnUiThread(); |
275 LauncherThread.post(new Runnable() { | 275 LauncherThread.post(new Runnable() { |
276 @Override | 276 @Override |
277 public void run() { | 277 public void run() { |
278 if (sSpareSandboxedConnection != null) return; | 278 if (sSpareSandboxedConnection != null) return; |
279 ChildProcessCreationParams params = ChildProcessCreationParams.g
etDefault(); | 279 ChildProcessCreationParams params = ChildProcessCreationParams.g
etDefault(); |
280 | 280 |
281 ChildProcessConnection.StartCallback startCallback = | 281 BaseChildProcessConnection.StartCallback startCallback = |
282 new ChildProcessConnection.StartCallback() { | 282 new BaseChildProcessConnection.StartCallback() { |
283 @Override | 283 @Override |
284 public void onChildStarted() { | 284 public void onChildStarted() { |
285 assert LauncherThread.runningOnLauncherThread(); | 285 assert LauncherThread.runningOnLauncherThread(); |
286 sSpareConnectionStarting = false; | 286 sSpareConnectionStarting = false; |
287 if (sSpareConnectionStartCallback != null) { | 287 if (sSpareConnectionStartCallback != null) { |
288 sSpareConnectionStartCallback.onChildStarted
(); | 288 sSpareConnectionStartCallback.onChildStarted
(); |
289 clearSpareConnection(); | 289 clearSpareConnection(); |
290 } | 290 } |
291 // If there is no chained callback, that means n
othing has tried to | 291 // If there is no chained callback, that means n
othing has tried to |
292 // use the spare connection yet. It will be clea
red when it is used | 292 // use the spare connection yet. It will be clea
red when it is used |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 boolean alwaysInForeground = false; | 340 boolean alwaysInForeground = false; |
341 String processType = | 341 String processType = |
342 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT
CH_PROCESS_TYPE); | 342 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT
CH_PROCESS_TYPE); |
343 ChildProcessCreationParams params = ChildProcessCreationParams.get(param
Id); | 343 ChildProcessCreationParams params = ChildProcessCreationParams.get(param
Id); |
344 if (paramId != ChildProcessCreationParams.DEFAULT_ID && params == null)
{ | 344 if (paramId != ChildProcessCreationParams.DEFAULT_ID && params == null)
{ |
345 throw new RuntimeException("CreationParams id " + paramId + " not fo
und"); | 345 throw new RuntimeException("CreationParams id " + paramId + " not fo
und"); |
346 } | 346 } |
347 if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { | 347 if (!ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { |
348 if (params != null && !params.getPackageName().equals(context.getPac
kageName())) { | 348 if (params != null && !params.getPackageName().equals(context.getPac
kageName())) { |
349 // WebViews and WebAPKs have renderer processes running in their
applications. | 349 // WebViews and WebAPKs have renderer processes running in their
applications. |
350 // When launching these renderer processes, {@link ChildProcessC
onnectionImpl} | 350 // When launching these renderer processes, {@link ManagedChildP
rocessConnection} |
351 // requires the package name of the application which holds the
renderer process. | 351 // requires the package name of the application which holds the
renderer process. |
352 // Therefore, the package name in ChildProcessCreationParams cou
ld be the package | 352 // Therefore, the package name in ChildProcessCreationParams cou
ld be the package |
353 // name of WebViews, WebAPKs, or Chrome, depending on the host a
pplication. | 353 // name of WebViews, WebAPKs, or Chrome, depending on the host a
pplication. |
354 // Except renderer process, all other child processes should use
Chrome's package | 354 // Except renderer process, all other child processes should use
Chrome's package |
355 // name. In WebAPK, ChildProcessCreationParams are initialized w
ith WebAPK's | 355 // name. In WebAPK, ChildProcessCreationParams are initialized w
ith WebAPK's |
356 // package name. Make a copy of the WebAPK's params, but replace
the package with | 356 // package name. Make a copy of the WebAPK's params, but replace
the package with |
357 // Chrome's package to use when initializing a non-renderer proc
esses. | 357 // Chrome's package to use when initializing a non-renderer proc
esses. |
358 // TODO(boliu): Should fold into |paramId|. Investigate why this
is needed. | 358 // TODO(boliu): Should fold into |paramId|. Investigate why this
is needed. |
359 params = new ChildProcessCreationParams(context.getPackageName()
, | 359 params = new ChildProcessCreationParams(context.getPackageName()
, |
360 params.getIsExternalService(), params.getLibraryProcessT
ype(), | 360 params.getIsExternalService(), params.getLibraryProcessT
ype(), |
361 params.getBindToCallerCheck()); | 361 params.getBindToCallerCheck()); |
362 } | 362 } |
363 if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { | 363 if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { |
364 childProcessCallback = new GpuProcessCallback(); | 364 childProcessCallback = new GpuProcessCallback(); |
365 inSandbox = false; | 365 inSandbox = false; |
366 alwaysInForeground = true; | 366 alwaysInForeground = true; |
367 } else { | 367 } else { |
368 // We only support sandboxed utility processes now. | 368 // We only support sandboxed utility processes now. |
369 assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType
); | 369 assert ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType
); |
370 } | 370 } |
371 } | 371 } |
372 | 372 |
373 startInternal(context, commandLine, childProcessId, filesToBeMapped, lau
nchCallback, | 373 startInternal(context, commandLine, childProcessId, filesToBeMapped, lau
nchCallback, |
374 childProcessCallback, inSandbox, alwaysInForeground, params); | 374 childProcessCallback, inSandbox, alwaysInForeground, params); |
375 } | 375 } |
376 | 376 |
377 @VisibleForTesting | 377 @VisibleForTesting |
378 public static ChildProcessConnection startInternal(final Context context, | 378 public static BaseChildProcessConnection startInternal(final Context context
, |
379 final String[] commandLine, final int childProcessId, | 379 final String[] commandLine, final int childProcessId, |
380 final FileDescriptorInfo[] filesToBeMapped, final LaunchCallback lau
nchCallback, | 380 final FileDescriptorInfo[] filesToBeMapped, final LaunchCallback lau
nchCallback, |
381 final IBinder childProcessCallback, final boolean inSandbox, | 381 final IBinder childProcessCallback, final boolean inSandbox, |
382 final boolean alwaysInForeground, final ChildProcessCreationParams c
reationParams) { | 382 final boolean alwaysInForeground, final ChildProcessCreationParams c
reationParams) { |
383 assert LauncherThread.runningOnLauncherThread(); | 383 assert LauncherThread.runningOnLauncherThread(); |
384 try { | 384 try { |
385 TraceEvent.begin("ChildProcessLauncher.startInternal"); | 385 TraceEvent.begin("ChildProcessLauncher.startInternal"); |
386 | 386 |
387 ChildProcessConnection allocatedConnection = null; | 387 BaseChildProcessConnection allocatedConnection = null; |
388 String packageName = creationParams != null ? creationParams.getPack
ageName() | 388 String packageName = creationParams != null ? creationParams.getPack
ageName() |
389 : context.getPackageName(); | 389 : context.getPackageName(); |
390 ChildProcessConnection.StartCallback startCallback = | 390 BaseChildProcessConnection.StartCallback startCallback = |
391 new ChildProcessConnection.StartCallback() { | 391 new BaseChildProcessConnection.StartCallback() { |
392 @Override | 392 @Override |
393 public void onChildStarted() {} | 393 public void onChildStarted() {} |
394 | 394 |
395 @Override | 395 @Override |
396 public void onChildStartFailed() { | 396 public void onChildStartFailed() { |
397 assert LauncherThread.runningOnLauncherThread(); | 397 assert LauncherThread.runningOnLauncherThread(); |
398 Log.e(TAG, "ChildProcessConnection.start failed, try
ing again"); | 398 Log.e(TAG, "BaseChildProcessConnection.start failed,
trying again"); |
399 LauncherThread.post(new Runnable() { | 399 LauncherThread.post(new Runnable() { |
400 @Override | 400 @Override |
401 public void run() { | 401 public void run() { |
402 // The child process may already be bound to
another client | 402 // The child process may already be bound to
another client |
403 // (this can happen if multi-process WebView
is used in more | 403 // (this can happen if multi-process WebView
is used in more |
404 // than one process), so try starting the pr
ocess again. | 404 // than one process), so try starting the pr
ocess again. |
405 // This connection that failed to start has
not been freed, | 405 // This connection that failed to start has
not been freed, |
406 // so a new bound connection will be allocat
ed. | 406 // so a new bound connection will be allocat
ed. |
407 startInternal(context, commandLine, childPro
cessId, | 407 startInternal(context, commandLine, childPro
cessId, |
408 filesToBeMapped, launchCallback, chi
ldProcessCallback, | 408 filesToBeMapped, launchCallback, chi
ldProcessCallback, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 Bundle bundle = new Bundle(); | 457 Bundle bundle = new Bundle(); |
458 bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, commandL
ine); | 458 bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, commandL
ine); |
459 bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, filesToBeMa
pped); | 459 bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, filesToBeMa
pped); |
460 bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCoun
t()); | 460 bundle.putInt(ChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCoun
t()); |
461 bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.get
Mask()); | 461 bundle.putLong(ChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.get
Mask()); |
462 bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS, Linker.getInstance()
.getSharedRelros()); | 462 bundle.putBundle(Linker.EXTRA_LINKER_SHARED_RELROS, Linker.getInstance()
.getSharedRelros()); |
463 return bundle; | 463 return bundle; |
464 } | 464 } |
465 | 465 |
466 @VisibleForTesting | 466 @VisibleForTesting |
467 static void triggerConnectionSetup(final ChildProcessConnection connection, | 467 static void triggerConnectionSetup(final BaseChildProcessConnection connecti
on, |
468 String[] commandLine, int childProcessId, FileDescriptorInfo[] files
ToBeMapped, | 468 String[] commandLine, int childProcessId, FileDescriptorInfo[] files
ToBeMapped, |
469 final IBinder childProcessCallback, final LaunchCallback launchCallb
ack) { | 469 final IBinder childProcessCallback, final LaunchCallback launchCallb
ack) { |
470 assert LauncherThread.runningOnLauncherThread(); | 470 assert LauncherThread.runningOnLauncherThread(); |
471 Log.d(TAG, "Setting up connection to process: slot=%d", connection.getSe
rviceNumber()); | 471 Log.d(TAG, "Setting up connection to process: slot=%d", connection.getSe
rviceNumber()); |
472 ChildProcessConnection.ConnectionCallback connectionCallback = | 472 BaseChildProcessConnection.ConnectionCallback connectionCallback = |
473 new ChildProcessConnection.ConnectionCallback() { | 473 new BaseChildProcessConnection.ConnectionCallback() { |
474 @Override | 474 @Override |
475 public void onConnected(int pid) { | 475 public void onConnected(BaseChildProcessConnection connectio
n) { |
476 Log.d(TAG, "on connect callback, pid=%d", pid); | 476 if (connection != null) { |
477 if (pid != NULL_PROCESS_HANDLE) { | 477 int pid = connection.getPid(); |
478 getBindingManager().addNewConnection(pid, connection
); | 478 Log.d(TAG, "on connect callback, pid=%d", pid); |
| 479 if (connection instanceof ManagedChildProcessConnect
ion) { |
| 480 getBindingManager().addNewConnection( |
| 481 pid, (ManagedChildProcessConnection) con
nection); |
| 482 } |
479 sServiceMap.put(pid, connection); | 483 sServiceMap.put(pid, connection); |
480 } | 484 } |
481 // If the connection fails and pid == 0, the Java-side c
leanup was already | 485 // If the connection fails and pid == 0, the Java-side c
leanup was already |
482 // handled by DeathCallback. We still have to call back
to native for | 486 // handled by DeathCallback. We still have to call back
to native for |
483 // cleanup there. | 487 // cleanup there. |
484 if (launchCallback != null) { // Will be null in Java in
strumentation tests. | 488 if (launchCallback != null) { // Will be null in Java in
strumentation tests. |
485 launchCallback.onChildProcessStarted(pid); | 489 launchCallback.onChildProcessStarted(connection); |
486 } | 490 } |
487 } | 491 } |
488 }; | 492 }; |
489 | 493 |
490 connection.setupConnection( | 494 connection.setupConnection( |
491 commandLine, filesToBeMapped, childProcessCallback, connectionCa
llback); | 495 commandLine, filesToBeMapped, childProcessCallback, connectionCa
llback); |
492 } | 496 } |
493 | 497 |
494 /** | 498 /** |
495 * Terminates a child process. This may be called from any thread. | 499 * Terminates a child process. This may be called from any thread. |
496 * | 500 * |
497 * @param pid The pid (process handle) of the service connection obtained fr
om {@link #start}. | 501 * @param pid The pid (process handle) of the service connection obtained fr
om {@link #start}. |
498 */ | 502 */ |
499 static void stop(int pid) { | 503 static void stop(int pid) { |
500 assert LauncherThread.runningOnLauncherThread(); | 504 assert LauncherThread.runningOnLauncherThread(); |
501 Log.d(TAG, "stopping child connection: pid=%d", pid); | 505 Log.d(TAG, "stopping child connection: pid=%d", pid); |
502 ChildProcessConnection connection = sServiceMap.remove(pid); | 506 BaseChildProcessConnection connection = sServiceMap.remove(pid); |
503 if (connection == null) { | 507 if (connection == null) { |
504 // Can happen for single process. | 508 // Can happen for single process. |
505 return; | 509 return; |
506 } | 510 } |
507 getBindingManager().clearConnection(pid); | 511 getBindingManager().removeConnection(pid); |
508 connection.stop(); | 512 connection.stop(); |
509 freeConnection(connection); | 513 freeConnection(connection); |
510 } | 514 } |
511 | 515 |
512 /** @return the count of services set up and working */ | 516 /** @return the count of services set up and working */ |
513 @VisibleForTesting | 517 @VisibleForTesting |
514 static int connectedServicesCountForTesting() { | 518 static int connectedServicesCountForTesting() { |
515 return sServiceMap.size(); | 519 return sServiceMap.size(); |
516 } | 520 } |
517 | 521 |
518 /** | 522 /** |
519 * Kills the child process for testing. | 523 * Kills the child process for testing. |
520 * @return true iff the process was killed as expected | 524 * @return true iff the process was killed as expected |
521 */ | 525 */ |
522 @VisibleForTesting | 526 @VisibleForTesting |
523 public static boolean crashProcessForTesting(int pid) { | 527 public static boolean crashProcessForTesting(int pid) { |
524 if (sServiceMap.get(pid) == null) return false; | 528 if (sServiceMap.get(pid) == null) return false; |
525 | 529 |
526 try { | 530 try { |
527 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT
esting(); | 531 ((ManagedChildProcessConnection) sServiceMap.get(pid)).crashServiceF
orTesting(); |
528 } catch (RemoteException ex) { | 532 } catch (RemoteException ex) { |
529 return false; | 533 return false; |
530 } | 534 } |
531 | 535 |
532 return true; | 536 return true; |
533 } | 537 } |
534 } | 538 } |
OLD | NEW |