Chromium Code Reviews| 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; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 import org.chromium.content.app.ChromiumLinkerParams; | 31 import org.chromium.content.app.ChromiumLinkerParams; |
| 32 import org.chromium.content.app.DownloadProcessService; | 32 import org.chromium.content.app.DownloadProcessService; |
| 33 import org.chromium.content.app.PrivilegedProcessService; | 33 import org.chromium.content.app.PrivilegedProcessService; |
| 34 import org.chromium.content.app.SandboxedProcessService; | 34 import org.chromium.content.app.SandboxedProcessService; |
| 35 import org.chromium.content.common.ContentSwitches; | 35 import org.chromium.content.common.ContentSwitches; |
| 36 import org.chromium.content.common.IChildProcessCallback; | 36 import org.chromium.content.common.IChildProcessCallback; |
| 37 import org.chromium.content.common.SurfaceWrapper; | 37 import org.chromium.content.common.SurfaceWrapper; |
| 38 | 38 |
| 39 import java.io.IOException; | 39 import java.io.IOException; |
| 40 import java.util.ArrayList; | 40 import java.util.ArrayList; |
| 41 import java.util.HashMap; | |
| 41 import java.util.LinkedList; | 42 import java.util.LinkedList; |
| 42 import java.util.Map; | 43 import java.util.Map; |
| 43 import java.util.Queue; | 44 import java.util.Queue; |
| 44 import java.util.concurrent.ConcurrentHashMap; | 45 import java.util.concurrent.ConcurrentHashMap; |
| 45 | 46 |
| 46 /** | 47 /** |
| 47 * This class provides the method to start/stop ChildProcess called by native. | 48 * This class provides the method to start/stop ChildProcess called by native. |
| 48 */ | 49 */ |
| 49 @JNINamespace("content") | 50 @JNINamespace("content") |
| 50 public class ChildProcessLauncher { | 51 public class ChildProcessLauncher { |
| 51 private static final String TAG = "ChildProcLauncher"; | 52 private static final String TAG = "ChildProcLauncher"; |
| 52 | 53 |
| 53 static final int CALLBACK_FOR_UNKNOWN_PROCESS = 0; | 54 static final int CALLBACK_FOR_UNKNOWN_PROCESS = 0; |
| 54 static final int CALLBACK_FOR_GPU_PROCESS = 1; | 55 static final int CALLBACK_FOR_GPU_PROCESS = 1; |
| 55 static final int CALLBACK_FOR_RENDERER_PROCESS = 2; | 56 static final int CALLBACK_FOR_RENDERER_PROCESS = 2; |
| 56 static final int CALLBACK_FOR_UTILITY_PROCESS = 3; | 57 static final int CALLBACK_FOR_UTILITY_PROCESS = 3; |
| 57 static final int CALLBACK_FOR_DOWNLOAD_PROCESS = 4; | 58 static final int CALLBACK_FOR_DOWNLOAD_PROCESS = 4; |
| 58 | 59 |
| 59 private static class ChildConnectionAllocator { | 60 private static class ChildConnectionAllocator { |
| 60 // Connections to services. Indices of the array correspond to the servi ce numbers. | 61 // Connections to services. Indices of the array correspond to the servi ce numbers. |
| 61 private final ChildProcessConnection[] mChildProcessConnections; | 62 private final ChildProcessConnection[] mChildProcessConnections; |
| 62 | 63 |
| 63 // The list of free (not bound) service indices. | 64 // The list of free (not bound) service indices. |
| 64 // SHOULD BE ACCESSED WITH mConnectionLock. | 65 // SHOULD BE ACCESSED WITH mConnectionLock. |
| 65 private final ArrayList<Integer> mFreeConnectionIndices; | 66 private final ArrayList<Integer> mFreeConnectionIndices; |
| 66 private final Object mConnectionLock = new Object(); | 67 private final Object mConnectionLock = new Object(); |
| 67 | 68 |
| 68 private Class<? extends ChildProcessService> mChildClass; | 69 private Class<? extends ChildProcessService> mChildClass; |
| 69 private final boolean mInSandbox; | 70 private final boolean mInSandbox; |
| 71 // Each Allocator keeps an queue for the pending spawn data. Once a conn ection is free, we | |
| 72 // dequeue the pending spawn data from the same allocator as the connect ion. | |
| 73 private PendingSpawnQueue mPendingSpawnQueue = new PendingSpawnQueue(); | |
|
Maria
2016/06/07 17:20:17
final?
an queue -> a queue.
Xi Han
2016/06/07 18:50:00
Done.
| |
| 70 | 74 |
| 71 public ChildConnectionAllocator(boolean inSandbox, int numChildServices) { | 75 public ChildConnectionAllocator(boolean inSandbox, int numChildServices) { |
| 72 mChildProcessConnections = new ChildProcessConnectionImpl[numChildSe rvices]; | 76 mChildProcessConnections = new ChildProcessConnectionImpl[numChildSe rvices]; |
| 73 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); | 77 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); |
| 74 for (int i = 0; i < numChildServices; i++) { | 78 for (int i = 0; i < numChildServices; i++) { |
| 75 mFreeConnectionIndices.add(i); | 79 mFreeConnectionIndices.add(i); |
| 76 } | 80 } |
| 77 mChildClass = | 81 mChildClass = |
| 78 inSandbox ? SandboxedProcessService.class : PrivilegedProces sService.class; | 82 inSandbox ? SandboxedProcessService.class : PrivilegedProces sService.class; |
| 79 mInSandbox = inSandbox; | 83 mInSandbox = inSandbox; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 } | 122 } |
| 119 } | 123 } |
| 120 } | 124 } |
| 121 | 125 |
| 122 public boolean isFreeConnectionAvailable() { | 126 public boolean isFreeConnectionAvailable() { |
| 123 synchronized (mConnectionLock) { | 127 synchronized (mConnectionLock) { |
| 124 return !mFreeConnectionIndices.isEmpty(); | 128 return !mFreeConnectionIndices.isEmpty(); |
| 125 } | 129 } |
| 126 } | 130 } |
| 127 | 131 |
| 132 public PendingSpawnQueue getPendingSpawnQueue() { | |
| 133 return mPendingSpawnQueue; | |
| 134 } | |
| 135 | |
| 128 /** @return the count of connections managed by the allocator */ | 136 /** @return the count of connections managed by the allocator */ |
| 129 @VisibleForTesting | 137 @VisibleForTesting |
| 130 int allocatedConnectionsCountForTesting() { | 138 int allocatedConnectionsCountForTesting() { |
| 131 return mChildProcessConnections.length - mFreeConnectionIndices.size (); | 139 return mChildProcessConnections.length - mFreeConnectionIndices.size (); |
| 132 } | 140 } |
| 133 } | 141 } |
| 134 | 142 |
| 135 private static class PendingSpawnData { | 143 private static class PendingSpawnData { |
| 136 private final Context mContext; | 144 private final Context mContext; |
| 137 private final String[] mCommandLine; | 145 private final String[] mCommandLine; |
| 138 private final int mChildProcessId; | 146 private final int mChildProcessId; |
| 139 private final FileDescriptorInfo[] mFilesToBeMapped; | 147 private final FileDescriptorInfo[] mFilesToBeMapped; |
| 140 private final long mClientContext; | 148 private final long mClientContext; |
| 141 private final int mCallbackType; | 149 private final int mCallbackType; |
| 142 private final boolean mInSandbox; | 150 private final boolean mInSandbox; |
| 151 private final ChildProcessCreationParams mCreationParams; | |
| 143 | 152 |
| 144 private PendingSpawnData( | 153 private PendingSpawnData( |
| 145 Context context, | 154 Context context, |
| 146 String[] commandLine, | 155 String[] commandLine, |
| 147 int childProcessId, | 156 int childProcessId, |
| 148 FileDescriptorInfo[] filesToBeMapped, | 157 FileDescriptorInfo[] filesToBeMapped, |
| 149 long clientContext, | 158 long clientContext, |
| 150 int callbackType, | 159 int callbackType, |
| 151 boolean inSandbox) { | 160 boolean inSandbox, |
| 161 ChildProcessCreationParams creationParams) { | |
| 152 mContext = context; | 162 mContext = context; |
| 153 mCommandLine = commandLine; | 163 mCommandLine = commandLine; |
| 154 mChildProcessId = childProcessId; | 164 mChildProcessId = childProcessId; |
| 155 mFilesToBeMapped = filesToBeMapped; | 165 mFilesToBeMapped = filesToBeMapped; |
| 156 mClientContext = clientContext; | 166 mClientContext = clientContext; |
| 157 mCallbackType = callbackType; | 167 mCallbackType = callbackType; |
| 158 mInSandbox = inSandbox; | 168 mInSandbox = inSandbox; |
| 169 mCreationParams = creationParams; | |
| 159 } | 170 } |
| 160 | 171 |
| 161 private Context context() { | 172 private Context context() { |
| 162 return mContext; | 173 return mContext; |
| 163 } | 174 } |
| 164 private String[] commandLine() { | 175 private String[] commandLine() { |
| 165 return mCommandLine; | 176 return mCommandLine; |
| 166 } | 177 } |
| 167 private int childProcessId() { | 178 private int childProcessId() { |
| 168 return mChildProcessId; | 179 return mChildProcessId; |
| 169 } | 180 } |
| 170 private FileDescriptorInfo[] filesToBeMapped() { | 181 private FileDescriptorInfo[] filesToBeMapped() { |
| 171 return mFilesToBeMapped; | 182 return mFilesToBeMapped; |
| 172 } | 183 } |
| 173 private long clientContext() { | 184 private long clientContext() { |
| 174 return mClientContext; | 185 return mClientContext; |
| 175 } | 186 } |
| 176 private int callbackType() { | 187 private int callbackType() { |
| 177 return mCallbackType; | 188 return mCallbackType; |
| 178 } | 189 } |
| 179 private boolean inSandbox() { | 190 private boolean inSandbox() { |
| 180 return mInSandbox; | 191 return mInSandbox; |
| 181 } | 192 } |
| 193 private ChildProcessCreationParams getCreationParams() { | |
| 194 return mCreationParams; | |
| 195 } | |
| 182 } | 196 } |
| 183 | 197 |
| 184 private static class PendingSpawnQueue { | 198 private static class PendingSpawnQueue { |
| 185 // The list of pending process spawn requests and its lock. | 199 // The list of pending process spawn requests and its lock. |
| 186 // Operations on this queue must be atomical w.r.t. free connections upd ates. | 200 // Operations on this queue must be atomical w.r.t. free connections upd ates. |
| 187 private static Queue<PendingSpawnData> sPendingSpawns = | 201 private Queue<PendingSpawnData> mPendingSpawns = |
| 188 new LinkedList<PendingSpawnData>(); | 202 new LinkedList<PendingSpawnData>(); |
|
Maria
2016/06/07 17:20:17
fits on one line
Xi Han
2016/06/07 18:49:59
Done.
| |
| 189 static final Object sPendingSpawnsLock = new Object(); | 203 final Object mPendingSpawnsLock = new Object(); |
|
Maria
2016/06/07 17:20:17
Now that the queue of spawns isn't static, do we s
Xi Han
2016/06/07 18:50:00
Good catch. Remove the lock.
| |
| 190 | 204 |
| 191 /** | 205 /** |
| 192 * Queue up a spawn requests to be processed once a free service is avai lable. | 206 * Queue up a spawn requests to be processed once a free service is avai lable. |
| 193 * Called when a spawn is requested while we are at the capacity. | 207 * Called when a spawn is requested while we are at the capacity. |
| 194 */ | 208 */ |
| 195 public void enqueueLocked(final PendingSpawnData pendingSpawn) { | 209 public void enqueueLocked(final PendingSpawnData pendingSpawn) { |
| 196 assert Thread.holdsLock(sPendingSpawnsLock); | 210 assert Thread.holdsLock(mPendingSpawnsLock); |
| 197 sPendingSpawns.add(pendingSpawn); | 211 mPendingSpawns.add(pendingSpawn); |
| 198 } | 212 } |
| 199 | 213 |
| 200 /** | 214 /** |
| 201 * Pop the next request from the queue. Called when a free service is av ailable. | 215 * 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. | 216 * @return the next spawn request waiting in the queue. |
| 203 */ | 217 */ |
| 204 public PendingSpawnData dequeueLocked() { | 218 public PendingSpawnData dequeueLocked() { |
| 205 assert Thread.holdsLock(sPendingSpawnsLock); | 219 assert Thread.holdsLock(mPendingSpawnsLock); |
| 206 return sPendingSpawns.poll(); | 220 return mPendingSpawns.poll(); |
| 207 } | 221 } |
| 208 | 222 |
| 209 /** @return the count of pending spawns in the queue */ | 223 /** @return the count of pending spawns in the queue */ |
| 210 public int sizeLocked() { | 224 public int sizeLocked() { |
| 211 assert Thread.holdsLock(sPendingSpawnsLock); | 225 assert Thread.holdsLock(mPendingSpawnsLock); |
| 212 return sPendingSpawns.size(); | 226 return mPendingSpawns.size(); |
| 213 } | 227 } |
| 214 } | 228 } |
| 215 | 229 |
| 216 private static final PendingSpawnQueue sPendingSpawnQueue = new PendingSpawn Queue(); | 230 // Service class for child process. |
| 217 | 231 // Map from package name to ChildConnectionAllocator; |
|
Maria
2016/06/07 17:20:17
; -> .
Xi Han
2016/06/07 18:50:00
Done.
| |
| 218 // Service class for child process. As the default value it uses SandboxedPr ocessService0 and | 232 private static Map<String, ChildConnectionAllocator> sSandboxedChildConnecti onAllocatorMap; |
| 219 // PrivilegedProcessService0. | 233 // As the default value it uses PrivilegedProcessService0. |
| 220 private static ChildConnectionAllocator sSandboxedChildConnectionAllocator; | |
| 221 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; | 234 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; |
| 222 | 235 |
| 223 private static final String NUM_SANDBOXED_SERVICES_KEY = | 236 private static final String NUM_SANDBOXED_SERVICES_KEY = |
| 224 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; | 237 "org.chromium.content.browser.NUM_SANDBOXED_SERVICES"; |
| 225 private static final String NUM_PRIVILEGED_SERVICES_KEY = | 238 private static final String NUM_PRIVILEGED_SERVICES_KEY = |
| 226 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; | 239 "org.chromium.content.browser.NUM_PRIVILEGED_SERVICES"; |
| 227 // Overrides the number of available sandboxed services. | 240 // Overrides the number of available sandboxed services. |
| 228 @VisibleForTesting | 241 @VisibleForTesting |
| 229 public static final String SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING = "num- sandboxed-services"; | 242 public static final String SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING = "num- sandboxed-services"; |
| 230 | 243 |
| 231 private static int getNumberOfServices(Context context, boolean inSandbox) { | 244 private static int getNumberOfServices(Context context, boolean inSandbox, S tring packageName) { |
| 232 try { | 245 try { |
| 233 PackageManager packageManager = context.getPackageManager(); | 246 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, | 247 ApplicationInfo appInfo = packageManager.getApplicationInfo(packageN ame, |
| 239 PackageManager.GET_META_DATA); | 248 PackageManager.GET_META_DATA); |
| 240 int numServices = appInfo.metaData.getInt(inSandbox ? NUM_SANDBOXED_ SERVICES_KEY | 249 int numServices = -1; |
| 241 : NUM_PRIVILEGED_SERVICES_KEY, -1); | 250 if (appInfo.metaData != null) { |
| 251 numServices = appInfo.metaData.getInt( | |
| 252 inSandbox ? NUM_SANDBOXED_SERVICES_KEY : NUM_PRIVILEGED_ SERVICES_KEY, -1); | |
| 253 } | |
| 242 if (inSandbox | 254 if (inSandbox |
| 243 && CommandLine.getInstance().hasSwitch( | 255 && CommandLine.getInstance().hasSwitch( |
| 244 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) { | 256 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING)) { |
| 245 String value = CommandLine.getInstance().getSwitchValue( | 257 String value = CommandLine.getInstance().getSwitchValue( |
| 246 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING); | 258 SWITCH_NUM_SANDBOXED_SERVICES_FOR_TESTING); |
| 247 if (!TextUtils.isEmpty(value)) { | 259 if (!TextUtils.isEmpty(value)) { |
| 248 try { | 260 try { |
| 249 numServices = Integer.parseInt(value); | 261 numServices = Integer.parseInt(value); |
| 250 } catch (NumberFormatException e) { | 262 } catch (NumberFormatException e) { |
| 251 Log.w(TAG, "The value of --num-sandboxed-services is for matted wrongly: " | 263 Log.w(TAG, "The value of --num-sandboxed-services is for matted wrongly: " |
| 252 + value); | 264 + value); |
| 253 } | 265 } |
| 254 } | 266 } |
| 255 } | 267 } |
| 256 if (numServices < 0) { | 268 if (numServices < 0) { |
| 257 throw new RuntimeException("Illegal meta data value for number o f child services"); | 269 throw new RuntimeException("Illegal meta data value for number o f child services"); |
| 258 } | 270 } |
| 259 return numServices; | 271 return numServices; |
| 260 } catch (PackageManager.NameNotFoundException e) { | 272 } catch (PackageManager.NameNotFoundException e) { |
| 261 throw new RuntimeException("Could not get application info"); | 273 throw new RuntimeException("Could not get application info"); |
| 262 } | 274 } |
| 263 } | 275 } |
| 264 | 276 |
| 265 private static void initConnectionAllocatorsIfNecessary(Context context) { | 277 private static void initConnectionAllocatorsIfNecessary( |
| 278 Context context, boolean inSandbox, String packageName) { | |
|
Maria
2016/06/07 17:20:17
it seems like previously this method allocated bot
Xi Han
2016/06/07 18:49:59
Yes, we can prevent the privileged process (GPU) i
| |
| 266 synchronized (ChildProcessLauncher.class) { | 279 synchronized (ChildProcessLauncher.class) { |
| 267 if (sSandboxedChildConnectionAllocator == null) { | 280 if (inSandbox) { |
| 268 sSandboxedChildConnectionAllocator = | 281 if (sSandboxedChildConnectionAllocatorMap == null) { |
| 269 new ChildConnectionAllocator(true, getNumberOfServices(c ontext, true)); | 282 sSandboxedChildConnectionAllocatorMap = |
| 283 new HashMap<String, ChildConnectionAllocator>(); | |
| 284 } | |
| 285 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageNa me)) { | |
| 286 Log.w(TAG, "Create a new ChildConnectionAllocator with packa ge name = %s," | |
| 287 + " inSandbox = true", | |
| 288 packageName); | |
| 289 sSandboxedChildConnectionAllocatorMap.put(packageName, | |
| 290 new ChildConnectionAllocator(true, | |
| 291 getNumberOfServices(context, true, packageNa me))); | |
| 292 } | |
| 293 } else if (sPrivilegedChildConnectionAllocator == null) { | |
| 294 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat or( | |
| 295 false, getNumberOfServices(context, false, packageName)) ; | |
| 270 } | 296 } |
| 271 if (sPrivilegedChildConnectionAllocator == null) { | 297 // TODO(pkotwicz|hanxi): Figure out when old allocators should be re moved from |
| 272 sPrivilegedChildConnectionAllocator = | 298 // {@code sSandboxedChildConnectionAllocatorMap}. |
| 273 new ChildConnectionAllocator(false, getNumberOfServices( context, false)); | |
| 274 } | |
| 275 } | 299 } |
| 276 } | 300 } |
| 277 | 301 |
| 278 private static ChildConnectionAllocator getConnectionAllocator(boolean inSan dbox) { | 302 /** |
| 279 return inSandbox | 303 * Note: please make sure that the Allocator has been initialized before cal ling this function. |
| 280 ? sSandboxedChildConnectionAllocator : sPrivilegedChildConnectio nAllocator; | 304 * Otherwise, always calls {@link initConnectionAllocatorsIfNecessary} first . |
| 305 */ | |
| 306 private static ChildConnectionAllocator getConnectionAllocator( | |
| 307 String packageName, boolean inSandbox) { | |
| 308 if (!inSandbox) { | |
| 309 return sPrivilegedChildConnectionAllocator; | |
| 310 } | |
| 311 return sSandboxedChildConnectionAllocatorMap.get(packageName); | |
| 312 } | |
| 313 | |
| 314 /** | |
| 315 * Get the PendingSpawnQueue of the Allocator. Initialize the Allocator if n eeded. | |
| 316 */ | |
| 317 private static PendingSpawnQueue getPendingSpawnQueue(Context context, Strin g packageName, | |
| 318 boolean inSandbox) { | |
| 319 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName); | |
| 320 return getConnectionAllocator(packageName, inSandbox).getPendingSpawnQue ue(); | |
| 281 } | 321 } |
| 282 | 322 |
| 283 private static ChildProcessConnection allocateConnection(Context context, bo olean inSandbox, | 323 private static ChildProcessConnection allocateConnection(Context context, bo olean inSandbox, |
| 284 ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForegroun d) { | 324 ChromiumLinkerParams chromiumLinkerParams, boolean alwaysInForegroun d, |
| 325 ChildProcessCreationParams creationParams) { | |
| 285 ChildProcessConnection.DeathCallback deathCallback = | 326 ChildProcessConnection.DeathCallback deathCallback = |
| 286 new ChildProcessConnection.DeathCallback() { | 327 new ChildProcessConnection.DeathCallback() { |
| 287 @Override | 328 @Override |
| 288 public void onChildProcessDied(ChildProcessConnection connec tion) { | 329 public void onChildProcessDied(ChildProcessConnection connec tion) { |
| 289 if (connection.getPid() != 0) { | 330 if (connection.getPid() != 0) { |
| 290 stop(connection.getPid()); | 331 stop(connection.getPid()); |
| 291 } else { | 332 } else { |
| 292 freeConnection(connection); | 333 freeConnection(connection); |
| 293 } | 334 } |
| 294 } | 335 } |
| 295 }; | 336 }; |
| 296 initConnectionAllocatorsIfNecessary(context); | 337 String packageName = creationParams != null ? creationParams.getPackageN ame() |
| 297 return getConnectionAllocator(inSandbox).allocate(context, deathCallback , | 338 : context.getPackageName(); |
| 298 chromiumLinkerParams, alwaysInForeground, ChildProcessCreationPa rams.get()); | 339 initConnectionAllocatorsIfNecessary(context, inSandbox, packageName); |
| 340 return getConnectionAllocator(packageName, inSandbox) | |
| 341 .allocate(context, deathCallback, chromiumLinkerParams, alwaysIn Foreground, | |
| 342 creationParams); | |
| 299 } | 343 } |
| 300 | 344 |
| 301 private static boolean sLinkerInitialized = false; | 345 private static boolean sLinkerInitialized = false; |
| 302 private static long sLinkerLoadAddress = 0; | 346 private static long sLinkerLoadAddress = 0; |
| 303 | 347 |
| 304 private static ChromiumLinkerParams getLinkerParamsForNewConnection() { | 348 private static ChromiumLinkerParams getLinkerParamsForNewConnection() { |
| 305 if (!sLinkerInitialized) { | 349 if (!sLinkerInitialized) { |
| 306 if (Linker.isUsed()) { | 350 if (Linker.isUsed()) { |
| 307 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress(); | 351 sLinkerLoadAddress = Linker.getInstance().getBaseLoadAddress(); |
| 308 if (sLinkerLoadAddress == 0) { | 352 if (sLinkerLoadAddress == 0) { |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 322 waitForSharedRelros, | 366 waitForSharedRelros, |
| 323 linker.getTestRunnerClassNameForTest ing(), | 367 linker.getTestRunnerClassNameForTest ing(), |
| 324 linker.getImplementationForTesting() ); | 368 linker.getImplementationForTesting() ); |
| 325 } else { | 369 } else { |
| 326 return new ChromiumLinkerParams(sLinkerLoadAddress, | 370 return new ChromiumLinkerParams(sLinkerLoadAddress, |
| 327 waitForSharedRelros); | 371 waitForSharedRelros); |
| 328 } | 372 } |
| 329 } | 373 } |
| 330 | 374 |
| 331 private static ChildProcessConnection allocateBoundConnection(Context contex t, | 375 private static ChildProcessConnection allocateBoundConnection(Context contex t, |
| 332 String[] commandLine, boolean inSandbox, boolean alwaysInForeground) { | 376 String[] commandLine, boolean inSandbox, boolean alwaysInForeground, |
| 377 ChildProcessCreationParams creationParams) { | |
| 333 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect ion(); | 378 ChromiumLinkerParams chromiumLinkerParams = getLinkerParamsForNewConnect ion(); |
| 334 ChildProcessConnection connection = allocateConnection(context, inSandbo x, | 379 ChildProcessConnection connection = allocateConnection( |
| 335 chromiumLinkerParams, alwaysInForeground); | 380 context, inSandbox, chromiumLinkerParams, alwaysInForeground, cr eationParams); |
| 336 if (connection != null) { | 381 if (connection != null) { |
| 337 connection.start(commandLine); | 382 connection.start(commandLine); |
| 338 | 383 |
| 339 if (inSandbox && !sSandboxedChildConnectionAllocator.isFreeConnectio nAvailable()) { | 384 String packageName = creationParams != null ? creationParams.getPack ageName() |
| 385 : context.getPackageName(); | |
| 386 if (inSandbox && !getConnectionAllocator(packageName, inSandbox) | |
| 387 .isFreeConnectionAvailable()) { | |
| 340 // Proactively releases all the moderate bindings once all the s andboxed services | 388 // 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 | 389 // are allocated, which will be very likely to have some of them killed by OOM |
| 342 // killer. | 390 // killer. |
| 343 sBindingManager.releaseAllModerateBindings(); | 391 sBindingManager.releaseAllModerateBindings(); |
| 344 } | 392 } |
| 345 } | 393 } |
| 346 return connection; | 394 return connection; |
| 347 } | 395 } |
| 348 | 396 |
| 349 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; | 397 private static final long FREE_CONNECTION_DELAY_MILLIS = 1; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 363 @Override | 411 @Override |
| 364 public void run() { | 412 public void run() { |
| 365 final PendingSpawnData pendingSpawn = freeConnectionAndDequeuePe nding(conn); | 413 final PendingSpawnData pendingSpawn = freeConnectionAndDequeuePe nding(conn); |
| 366 if (pendingSpawn != null) { | 414 if (pendingSpawn != null) { |
| 367 new Thread(new Runnable() { | 415 new Thread(new Runnable() { |
| 368 @Override | 416 @Override |
| 369 public void run() { | 417 public void run() { |
| 370 startInternal(pendingSpawn.context(), pendingSpawn.c ommandLine(), | 418 startInternal(pendingSpawn.context(), pendingSpawn.c ommandLine(), |
| 371 pendingSpawn.childProcessId(), pendingSpawn. filesToBeMapped(), | 419 pendingSpawn.childProcessId(), pendingSpawn. filesToBeMapped(), |
| 372 pendingSpawn.clientContext(), pendingSpawn.c allbackType(), | 420 pendingSpawn.clientContext(), pendingSpawn.c allbackType(), |
| 373 pendingSpawn.inSandbox()); | 421 pendingSpawn.inSandbox(), pendingSpawn.getCr eationParams()); |
| 374 } | 422 } |
| 375 }).start(); | 423 }).start(); |
| 376 } | 424 } |
| 377 } | 425 } |
| 378 }, FREE_CONNECTION_DELAY_MILLIS); | 426 }, FREE_CONNECTION_DELAY_MILLIS); |
| 379 } | 427 } |
| 380 | 428 |
| 381 private static PendingSpawnData freeConnectionAndDequeuePending(ChildProcess Connection conn) { | 429 private static PendingSpawnData freeConnectionAndDequeuePending(ChildProcess Connection conn) { |
| 382 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { | 430 ChildConnectionAllocator allocator = getConnectionAllocator( |
| 383 getConnectionAllocator(conn.isInSandbox()).free(conn); | 431 conn.getPackageName(), conn.isInSandbox()); |
| 384 return sPendingSpawnQueue.dequeueLocked(); | 432 assert allocator != null; |
| 433 PendingSpawnQueue pendingSpawnQueue = allocator.getPendingSpawnQueue(); | |
| 434 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { | |
| 435 allocator.free(conn); | |
| 436 return pendingSpawnQueue.dequeueLocked(); | |
| 385 } | 437 } |
| 386 } | 438 } |
| 387 | 439 |
| 388 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle. | 440 // Represents an invalid process handle; same as base/process/process.h kNul lProcessHandle. |
| 389 private static final int NULL_PROCESS_HANDLE = 0; | 441 private static final int NULL_PROCESS_HANDLE = 0; |
| 390 | 442 |
| 391 // Map from pid to ChildService connection. | 443 // Map from pid to ChildService connection. |
| 392 private static Map<Integer, ChildProcessConnection> sServiceMap = | 444 private static Map<Integer, ChildProcessConnection> sServiceMap = |
| 393 new ConcurrentHashMap<Integer, ChildProcessConnection>(); | 445 new ConcurrentHashMap<Integer, ChildProcessConnection>(); |
| 394 | 446 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 506 /** | 558 /** |
| 507 * Called when the embedding application is sent to background. | 559 * Called when the embedding application is sent to background. |
| 508 */ | 560 */ |
| 509 public static void onSentToBackground() { | 561 public static void onSentToBackground() { |
| 510 sApplicationInForeground = false; | 562 sApplicationInForeground = false; |
| 511 sBindingManager.onSentToBackground(); | 563 sBindingManager.onSentToBackground(); |
| 512 } | 564 } |
| 513 | 565 |
| 514 /** | 566 /** |
| 515 * Starts moderate binding management. | 567 * Starts moderate binding management. |
| 568 * Note: WebAPKs and non WebAPKs share the same moderate binding pool, so th e size of the | |
| 569 * shared moderate binding pool is always set based on the number of sandbox es processes | |
| 570 * used by Chrome. | |
| 516 * @param context Android's context. | 571 * @param context Android's context. |
| 517 * @param moderateBindingTillBackgrounded true if the BindingManager should add a moderate | 572 * @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 | 573 * binding to a render process when it is created and remove the moderate bi nding when Chrome is |
| 519 * sent to the background. | 574 * sent to the background. |
| 520 */ | 575 */ |
| 521 public static void startModerateBindingManagement( | 576 public static void startModerateBindingManagement( |
| 522 Context context, boolean moderateBindingTillBackgrounded) { | 577 Context context, boolean moderateBindingTillBackgrounded) { |
| 523 sBindingManager.startModerateBindingManagement( | 578 sBindingManager.startModerateBindingManagement(context, |
| 524 context, getNumberOfServices(context, true), moderateBindingTill Backgrounded); | 579 getNumberOfServices(context, true, context.getPackageName()), |
| 580 moderateBindingTillBackgrounded); | |
| 525 } | 581 } |
| 526 | 582 |
| 527 /** | 583 /** |
| 528 * Called when the embedding application is brought to foreground. | 584 * Called when the embedding application is brought to foreground. |
| 529 */ | 585 */ |
| 530 public static void onBroughtToForeground() { | 586 public static void onBroughtToForeground() { |
| 531 sApplicationInForeground = true; | 587 sApplicationInForeground = true; |
| 532 sBindingManager.onBroughtToForeground(); | 588 sBindingManager.onBroughtToForeground(); |
| 533 } | 589 } |
| 534 | 590 |
| 535 /** | 591 /** |
| 536 * Returns whether the application is currently in the foreground. | 592 * Returns whether the application is currently in the foreground. |
| 537 */ | 593 */ |
| 538 static boolean isApplicationInForeground() { | 594 static boolean isApplicationInForeground() { |
| 539 return sApplicationInForeground; | 595 return sApplicationInForeground; |
| 540 } | 596 } |
| 541 | 597 |
| 542 /** | 598 /** |
| 543 * Should be called early in startup so the work needed to spawn the child p rocess can be done | 599 * 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 | 600 * in parallel to other startup work. Must not be called on the UI thread. S pare connection is |
| 545 * created in sandboxed child process. | 601 * created in sandboxed child process. |
| 546 * @param context the application context used for the connection. | 602 * @param context the application context used for the connection. |
| 547 * @param params child process creation params. | |
| 548 */ | 603 */ |
| 549 public static void warmUp(Context context, ChildProcessCreationParams params ) { | 604 public static void warmUp(Context context) { |
| 550 ChildProcessCreationParams.set(params); | |
| 551 synchronized (ChildProcessLauncher.class) { | 605 synchronized (ChildProcessLauncher.class) { |
| 552 assert !ThreadUtils.runningOnUiThread(); | 606 assert !ThreadUtils.runningOnUiThread(); |
| 553 if (sSpareSandboxedConnection == null) { | 607 if (sSpareSandboxedConnection == null) { |
| 554 sSpareSandboxedConnection = allocateBoundConnection(context, nul l, true, false); | 608 ChildProcessCreationParams params = ChildProcessCreationParams.g et(); |
| 609 if (params != null) { | |
| 610 params = params.copy(); | |
| 611 } | |
| 612 sSpareSandboxedConnection = allocateBoundConnection(context, nul l, true, false, | |
| 613 params); | |
| 555 } | 614 } |
| 556 } | 615 } |
| 557 } | 616 } |
| 558 | 617 |
| 559 @CalledByNative | 618 @CalledByNative |
| 560 private static FileDescriptorInfo makeFdInfo( | 619 private static FileDescriptorInfo makeFdInfo( |
| 561 int id, int fd, boolean autoClose, long offset, long size) { | 620 int id, int fd, boolean autoClose, long offset, long size) { |
| 562 ParcelFileDescriptor pFd; | 621 ParcelFileDescriptor pFd; |
| 563 if (autoClose) { | 622 if (autoClose) { |
| 564 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor. | 623 // Adopt the FD, it will be closed when we close the ParcelFileDescr iptor. |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 587 */ | 646 */ |
| 588 @CalledByNative | 647 @CalledByNative |
| 589 private static void start(Context context, final String[] commandLine, int c hildProcessId, | 648 private static void start(Context context, final String[] commandLine, int c hildProcessId, |
| 590 FileDescriptorInfo[] filesToBeMapped, long clientContext) { | 649 FileDescriptorInfo[] filesToBeMapped, long clientContext) { |
| 591 assert clientContext != 0; | 650 assert clientContext != 0; |
| 592 | 651 |
| 593 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; | 652 int callbackType = CALLBACK_FOR_UNKNOWN_PROCESS; |
| 594 boolean inSandbox = true; | 653 boolean inSandbox = true; |
| 595 String processType = | 654 String processType = |
| 596 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE); | 655 ContentSwitches.getSwitchValue(commandLine, ContentSwitches.SWIT CH_PROCESS_TYPE); |
| 656 ChildProcessCreationParams params = null; | |
| 597 if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { | 657 if (ContentSwitches.SWITCH_RENDERER_PROCESS.equals(processType)) { |
| 598 callbackType = CALLBACK_FOR_RENDERER_PROCESS; | 658 callbackType = CALLBACK_FOR_RENDERER_PROCESS; |
| 659 if (ChildProcessCreationParams.get() != null) { | |
| 660 params = ChildProcessCreationParams.get().copy(); | |
| 661 } | |
| 599 } else if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { | 662 } else if (ContentSwitches.SWITCH_GPU_PROCESS.equals(processType)) { |
| 600 callbackType = CALLBACK_FOR_GPU_PROCESS; | 663 callbackType = CALLBACK_FOR_GPU_PROCESS; |
| 601 inSandbox = false; | 664 inSandbox = false; |
| 602 } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType)) { | 665 } else if (ContentSwitches.SWITCH_UTILITY_PROCESS.equals(processType)) { |
| 603 // We only support sandboxed right now. | 666 // We only support sandboxed right now. |
| 604 callbackType = CALLBACK_FOR_UTILITY_PROCESS; | 667 callbackType = CALLBACK_FOR_UTILITY_PROCESS; |
| 605 } else { | 668 } else { |
| 606 assert false; | 669 assert false; |
| 607 } | 670 } |
|
pkotwicz
2016/06/02 02:16:30
michaelbai@ would it be acceptable to set {@link p
michaelbai
2016/06/03 17:38:46
It is fine.
Xi Han
2016/06/03 18:03:36
Since I already added these checks, will leave the
| |
| 608 | 671 |
| 609 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli entContext, | 672 startInternal(context, commandLine, childProcessId, filesToBeMapped, cli entContext, |
| 610 callbackType, inSandbox); | 673 callbackType, inSandbox, params); |
| 611 } | 674 } |
| 612 | 675 |
| 613 /** | 676 /** |
| 614 * Spawns a background download process if it hasn't been started. The downl oad process will | 677 * 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. | 678 * manage its own lifecyle and can outlive chrome. |
| 616 * | 679 * |
| 617 * @param context Context used to obtain the application context. | 680 * @param context Context used to obtain the application context. |
| 618 * @param commandLine The child process command line argv. | 681 * @param commandLine The child process command line argv. |
| 619 */ | 682 */ |
| 620 @SuppressLint("NewApi") | 683 @SuppressLint("NewApi") |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 643 context.startService(intent); | 706 context.startService(intent); |
| 644 } | 707 } |
| 645 | 708 |
| 646 private static void startInternal( | 709 private static void startInternal( |
| 647 Context context, | 710 Context context, |
| 648 final String[] commandLine, | 711 final String[] commandLine, |
| 649 int childProcessId, | 712 int childProcessId, |
| 650 FileDescriptorInfo[] filesToBeMapped, | 713 FileDescriptorInfo[] filesToBeMapped, |
| 651 long clientContext, | 714 long clientContext, |
| 652 int callbackType, | 715 int callbackType, |
| 653 boolean inSandbox) { | 716 boolean inSandbox, |
| 717 ChildProcessCreationParams creationParams) { | |
| 654 try { | 718 try { |
| 655 TraceEvent.begin("ChildProcessLauncher.startInternal"); | 719 TraceEvent.begin("ChildProcessLauncher.startInternal"); |
| 656 | 720 |
| 657 ChildProcessConnection allocatedConnection = null; | 721 ChildProcessConnection allocatedConnection = null; |
| 722 String packageName = creationParams != null ? creationParams.getPack ageName() | |
| 723 : context.getPackageName(); | |
| 658 synchronized (ChildProcessLauncher.class) { | 724 synchronized (ChildProcessLauncher.class) { |
| 659 if (inSandbox) { | 725 if (inSandbox && sSpareSandboxedConnection != null |
| 726 && sSpareSandboxedConnection.getPackageName().equals(pac kageName)) { | |
| 660 allocatedConnection = sSpareSandboxedConnection; | 727 allocatedConnection = sSpareSandboxedConnection; |
| 661 sSpareSandboxedConnection = null; | 728 sSpareSandboxedConnection = null; |
| 662 } | 729 } |
| 663 } | 730 } |
| 664 if (allocatedConnection == null) { | 731 if (allocatedConnection == null) { |
| 665 boolean alwaysInForeground = false; | 732 boolean alwaysInForeground = false; |
| 666 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true; | 733 if (callbackType == CALLBACK_FOR_GPU_PROCESS) alwaysInForeground = true; |
| 667 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { | 734 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue( |
| 735 context, packageName, inSandbox); | |
| 736 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { | |
| 668 allocatedConnection = allocateBoundConnection( | 737 allocatedConnection = allocateBoundConnection( |
| 669 context, commandLine, inSandbox, alwaysInForeground) ; | 738 context, commandLine, inSandbox, alwaysInForeground, creationParams); |
| 670 if (allocatedConnection == null) { | 739 if (allocatedConnection == null) { |
| 671 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn."); | 740 Log.d(TAG, "Allocation of new service failed. Queuing up pending spawn."); |
| 672 sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(co ntext, commandLine, | 741 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(con text, commandLine, |
| 673 childProcessId, filesToBeMapped, clientContext, | 742 childProcessId, filesToBeMapped, clientContext, |
| 674 callbackType, inSandbox)); | 743 callbackType, inSandbox, creationParams)); |
| 675 return; | 744 return; |
| 676 } | 745 } |
| 677 } | 746 } |
| 678 } | 747 } |
| 679 | 748 |
| 680 Log.d(TAG, "Setting up connection to process: slot=%d", | 749 Log.d(TAG, "Setting up connection to process: slot=%d", |
| 681 allocatedConnection.getServiceNumber()); | 750 allocatedConnection.getServiceNumber()); |
| 682 triggerConnectionSetup(allocatedConnection, commandLine, childProces sId, | 751 triggerConnectionSetup(allocatedConnection, commandLine, childProces sId, |
| 683 filesToBeMapped, callbackType, clientContext); | 752 filesToBeMapped, callbackType, clientContext); |
| 684 } finally { | 753 } finally { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 841 } | 910 } |
| 842 | 911 |
| 843 static void logPidWarning(int pid, String message) { | 912 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. | 913 // This class is effectively a no-op in single process mode, so don't lo g warnings there. |
| 845 if (pid > 0 && !nativeIsSingleProcess()) { | 914 if (pid > 0 && !nativeIsSingleProcess()) { |
| 846 Log.w(TAG, "%s, pid=%d", message, pid); | 915 Log.w(TAG, "%s, pid=%d", message, pid); |
| 847 } | 916 } |
| 848 } | 917 } |
| 849 | 918 |
| 850 @VisibleForTesting | 919 @VisibleForTesting |
| 851 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext) { | 920 static ChildProcessConnection allocateBoundConnectionForTesting(Context cont ext, |
| 852 return allocateBoundConnection(context, null, true, false); | 921 ChildProcessCreationParams creationParams) { |
| 922 return allocateBoundConnection(context, null, true, false, creationParam s); | |
| 853 } | 923 } |
| 854 | 924 |
| 855 /** | 925 /** |
| 856 * Queue up a spawn requests for testing. | 926 * Queue up a spawn requests for testing. |
| 857 */ | 927 */ |
| 858 @VisibleForTesting | 928 @VisibleForTesting |
| 859 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine) { | 929 static void enqueuePendingSpawnForTesting(Context context, String[] commandL ine, |
| 860 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { | 930 ChildProcessCreationParams creationParams, boolean inSandbox) { |
| 861 sPendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comma ndLine, 1, | 931 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, |
| 862 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true)); | 932 creationParams.getPackageName(), inSandbox); |
| 933 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { | |
| 934 pendingSpawnQueue.enqueueLocked(new PendingSpawnData(context, comman dLine, 1, | |
| 935 new FileDescriptorInfo[0], 0, CALLBACK_FOR_RENDERER_PROCESS, true, | |
| 936 creationParams)); | |
| 863 } | 937 } |
| 864 } | 938 } |
| 865 | 939 |
| 866 /** @return the count of sandboxed connections managed by the allocator */ | 940 /** |
| 941 * @return the number of sandboxed connections of given {@link packageName} managed by the | |
| 942 * allocator. | |
| 943 */ | |
| 867 @VisibleForTesting | 944 @VisibleForTesting |
| 868 static int allocatedConnectionsCountForTesting(Context context) { | 945 static int allocatedSandboxedConnectionsCountForTesting(Context context, Str ing packageName) { |
| 869 initConnectionAllocatorsIfNecessary(context); | 946 initConnectionAllocatorsIfNecessary(context, true, packageName); |
| 870 return sSandboxedChildConnectionAllocator.allocatedConnectionsCountForTe sting(); | 947 return sSandboxedChildConnectionAllocatorMap.get(packageName) |
| 948 .allocatedConnectionsCountForTesting(); | |
| 871 } | 949 } |
| 872 | 950 |
| 873 /** @return the count of services set up and working */ | 951 /** @return the count of services set up and working */ |
| 874 @VisibleForTesting | 952 @VisibleForTesting |
| 875 static int connectedServicesCountForTesting() { | 953 static int connectedServicesCountForTesting() { |
| 876 return sServiceMap.size(); | 954 return sServiceMap.size(); |
| 877 } | 955 } |
| 878 | 956 |
| 879 /** @return the count of pending spawns in the queue */ | 957 /** |
| 958 * @param context The context. | |
| 959 * @param packageName The package name of the {@link ChildProcessAlocator}. | |
| 960 * @param inSandbox Whether the connection is sandboxed. | |
| 961 * @return the count of pending spawns in the queue. | |
| 962 */ | |
| 880 @VisibleForTesting | 963 @VisibleForTesting |
| 881 static int pendingSpawnsCountForTesting() { | 964 static int pendingSpawnsCountForTesting(Context context, String packageName, |
| 882 synchronized (PendingSpawnQueue.sPendingSpawnsLock) { | 965 boolean inSandbox) { |
| 883 return sPendingSpawnQueue.sizeLocked(); | 966 PendingSpawnQueue pendingSpawnQueue = getPendingSpawnQueue(context, pack ageName, inSandbox); |
| 967 synchronized (pendingSpawnQueue.mPendingSpawnsLock) { | |
| 968 return pendingSpawnQueue.sizeLocked(); | |
| 884 } | 969 } |
| 885 } | 970 } |
| 886 | 971 |
| 887 /** | 972 /** |
| 888 * Kills the child process for testing. | 973 * Kills the child process for testing. |
| 889 * @return true iff the process was killed as expected | 974 * @return true iff the process was killed as expected |
| 890 */ | 975 */ |
| 891 @VisibleForTesting | 976 @VisibleForTesting |
| 892 public static boolean crashProcessForTesting(int pid) { | 977 public static boolean crashProcessForTesting(int pid) { |
| 893 if (sServiceMap.get(pid) == null) return false; | 978 if (sServiceMap.get(pid) == null) return false; |
| 894 | 979 |
| 895 try { | 980 try { |
| 896 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting(); | 981 ((ChildProcessConnectionImpl) sServiceMap.get(pid)).crashServiceForT esting(); |
| 897 } catch (RemoteException ex) { | 982 } catch (RemoteException ex) { |
| 898 return false; | 983 return false; |
| 899 } | 984 } |
| 900 | 985 |
| 901 return true; | 986 return true; |
| 902 } | 987 } |
| 903 | 988 |
| 904 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); | 989 private static native void nativeOnChildProcessStarted(long clientContext, i nt pid); |
| 905 private static native void nativeEstablishSurfacePeer( | 990 private static native void nativeEstablishSurfacePeer( |
| 906 int pid, Surface surface, int primaryID, int secondaryID); | 991 int pid, Surface surface, int primaryID, int secondaryID); |
| 907 private static native boolean nativeIsSingleProcess(); | 992 private static native boolean nativeIsSingleProcess(); |
| 908 } | 993 } |
| OLD | NEW |