| 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 */ |
| 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 */ |
| 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()) |
| 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()); |
| 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 */ |
| 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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) { |
| 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; |
| 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."); |
| 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 |
| (...skipping 161 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 |