| Index: content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java
|
| diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java b/content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java
|
| index 25872326fa838d1cbfa6e7fb4de6292205c75bb3..56230dda2078ccb330c5718391e25141d9819937 100644
|
| --- a/content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java
|
| +++ b/content/public/android/java/src/org/chromium/content/browser/ChildConnectionAllocator.java
|
| @@ -13,16 +13,15 @@ import android.text.TextUtils;
|
|
|
| import org.chromium.base.Log;
|
| import org.chromium.base.VisibleForTesting;
|
| +import org.chromium.base.annotations.SuppressFBWarnings;
|
| import org.chromium.content.app.PrivilegedProcessService;
|
| import org.chromium.content.app.SandboxedProcessService;
|
|
|
| import java.util.ArrayList;
|
| +import java.util.HashMap;
|
| import java.util.LinkedList;
|
| import java.util.Map;
|
| import java.util.Queue;
|
| -import java.util.concurrent.ConcurrentHashMap;
|
| -
|
| -import javax.annotation.concurrent.GuardedBy;
|
|
|
| /**
|
| * This class is responsible for allocating and managing connections to child
|
| @@ -39,14 +38,10 @@ public class ChildConnectionAllocator {
|
| private static final String SANDBOXED_SERVICES_NAME_KEY =
|
| "org.chromium.content.browser.SANDBOXED_SERVICES_NAME";
|
|
|
| - private static final Object sAllocatorLock = new Object();
|
| -
|
| // Map from package name to ChildConnectionAllocator.
|
| - @GuardedBy("sAllocatorLock")
|
| private static Map<String, ChildConnectionAllocator> sSandboxedChildConnectionAllocatorMap;
|
|
|
| // Allocator used for non-sandboxed services.
|
| - @GuardedBy("sAllocatorLock")
|
| private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator;
|
|
|
| // Used by test to override the default sandboxed service settings.
|
| @@ -59,47 +54,42 @@ public class ChildConnectionAllocator {
|
| private final String mChildClassName;
|
| private final boolean mInSandbox;
|
|
|
| - private final Object mConnectionLock = new Object();
|
| -
|
| // The list of free (not bound) service indices.
|
| - @GuardedBy("mConnectionLock")
|
| private final ArrayList<Integer> mFreeConnectionIndices;
|
|
|
| // Each Allocator keeps a queue for the pending spawn data. Once a connection is free, we
|
| // dequeue the pending spawn data from the same allocator as the connection.
|
| - @GuardedBy("mConnectionLock")
|
| private final Queue<ChildSpawnData> mPendingSpawnQueue = new LinkedList<>();
|
|
|
| + @SuppressFBWarnings("LI_LAZY_INIT_STATIC") // Method is single thread.
|
| public static ChildConnectionAllocator getAllocator(
|
| Context context, String packageName, boolean inSandbox) {
|
| - synchronized (sAllocatorLock) {
|
| - if (!inSandbox) {
|
| - if (sPrivilegedChildConnectionAllocator == null) {
|
| - sPrivilegedChildConnectionAllocator = new ChildConnectionAllocator(false,
|
| - getNumberOfServices(context, false, packageName),
|
| - getClassNameOfService(context, false, packageName));
|
| - }
|
| - return sPrivilegedChildConnectionAllocator;
|
| + assert LauncherThread.runningOnLauncherThread();
|
| + if (!inSandbox) {
|
| + if (sPrivilegedChildConnectionAllocator == null) {
|
| + sPrivilegedChildConnectionAllocator = new ChildConnectionAllocator(false,
|
| + getNumberOfServices(context, false, packageName),
|
| + getClassNameOfService(context, false, packageName));
|
| }
|
| + return sPrivilegedChildConnectionAllocator;
|
| + }
|
|
|
| - if (sSandboxedChildConnectionAllocatorMap == null) {
|
| - sSandboxedChildConnectionAllocatorMap =
|
| - new ConcurrentHashMap<String, ChildConnectionAllocator>();
|
| - }
|
| - if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageName)) {
|
| - Log.w(TAG,
|
| - "Create a new ChildConnectionAllocator with package name = %s,"
|
| - + " inSandbox = true",
|
| - packageName);
|
| - sSandboxedChildConnectionAllocatorMap.put(packageName,
|
| - new ChildConnectionAllocator(true,
|
| - getNumberOfServices(context, true, packageName),
|
| - getClassNameOfService(context, true, packageName)));
|
| - }
|
| - return sSandboxedChildConnectionAllocatorMap.get(packageName);
|
| - // TODO(pkotwicz|hanxi): Figure out when old allocators should be removed from
|
| - // {@code sSandboxedChildConnectionAllocatorMap}.
|
| + if (sSandboxedChildConnectionAllocatorMap == null) {
|
| + sSandboxedChildConnectionAllocatorMap = new HashMap<String, ChildConnectionAllocator>();
|
| }
|
| + if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageName)) {
|
| + Log.w(TAG,
|
| + "Create a new ChildConnectionAllocator with package name = %s,"
|
| + + " inSandbox = true",
|
| + packageName);
|
| + sSandboxedChildConnectionAllocatorMap.put(packageName,
|
| + new ChildConnectionAllocator(true,
|
| + getNumberOfServices(context, true, packageName),
|
| + getClassNameOfService(context, true, packageName)));
|
| + }
|
| + return sSandboxedChildConnectionAllocatorMap.get(packageName);
|
| + // TODO(pkotwicz|hanxi): Figure out when old allocators should be removed from
|
| + // {@code sSandboxedChildConnectionAllocatorMap}.
|
| }
|
|
|
| private static String getClassNameOfService(
|
| @@ -185,60 +175,56 @@ public class ChildConnectionAllocator {
|
| public ChildProcessConnection allocate(ChildSpawnData spawnData,
|
| ChildProcessConnection.DeathCallback deathCallback, Bundle childProcessCommonParameters,
|
| boolean queueIfNoSlotAvailable) {
|
| + assert LauncherThread.runningOnLauncherThread();
|
| assert spawnData.isInSandbox() == mInSandbox;
|
| - synchronized (mConnectionLock) {
|
| - if (mFreeConnectionIndices.isEmpty()) {
|
| - Log.d(TAG, "Ran out of services to allocate.");
|
| - if (queueIfNoSlotAvailable) {
|
| - mPendingSpawnQueue.add(spawnData);
|
| - }
|
| - return null;
|
| + if (mFreeConnectionIndices.isEmpty()) {
|
| + Log.d(TAG, "Ran out of services to allocate.");
|
| + if (queueIfNoSlotAvailable) {
|
| + mPendingSpawnQueue.add(spawnData);
|
| }
|
| - int slot = mFreeConnectionIndices.remove(0);
|
| - assert mChildProcessConnections[slot] == null;
|
| - mChildProcessConnections[slot] = new ChildProcessConnectionImpl(spawnData.getContext(),
|
| - slot, mInSandbox, deathCallback, mChildClassName, childProcessCommonParameters,
|
| - spawnData.isAlwaysInForeground(), spawnData.getCreationParams());
|
| - Log.d(TAG, "Allocator allocated a connection, sandbox: %b, slot: %d", mInSandbox, slot);
|
| - return mChildProcessConnections[slot];
|
| + return null;
|
| }
|
| + int slot = mFreeConnectionIndices.remove(0);
|
| + assert mChildProcessConnections[slot] == null;
|
| + mChildProcessConnections[slot] = new ChildProcessConnectionImpl(spawnData.getContext(),
|
| + slot, mInSandbox, deathCallback, mChildClassName, childProcessCommonParameters,
|
| + spawnData.isAlwaysInForeground(), spawnData.getCreationParams());
|
| + Log.d(TAG, "Allocator allocated a connection, sandbox: %b, slot: %d", mInSandbox, slot);
|
| + return mChildProcessConnections[slot];
|
| }
|
|
|
| // Also return the first ChildSpawnData in the pending queue, if any.
|
| public ChildSpawnData free(ChildProcessConnection connection) {
|
| - synchronized (mConnectionLock) {
|
| - int slot = connection.getServiceNumber();
|
| - if (mChildProcessConnections[slot] != connection) {
|
| - int occupier = mChildProcessConnections[slot] == null
|
| - ? -1
|
| - : mChildProcessConnections[slot].getServiceNumber();
|
| - Log.e(TAG,
|
| - "Unable to find connection to free in slot: %d "
|
| - + "already occupied by service: %d",
|
| - slot, occupier);
|
| - assert false;
|
| - } else {
|
| - mChildProcessConnections[slot] = null;
|
| - assert !mFreeConnectionIndices.contains(slot);
|
| - mFreeConnectionIndices.add(slot);
|
| - Log.d(TAG, "Allocator freed a connection, sandbox: %b, slot: %d", mInSandbox, slot);
|
| - }
|
| - return mPendingSpawnQueue.poll();
|
| + assert LauncherThread.runningOnLauncherThread();
|
| + int slot = connection.getServiceNumber();
|
| + if (mChildProcessConnections[slot] != connection) {
|
| + int occupier = mChildProcessConnections[slot] == null
|
| + ? -1
|
| + : mChildProcessConnections[slot].getServiceNumber();
|
| + Log.e(TAG,
|
| + "Unable to find connection to free in slot: %d "
|
| + + "already occupied by service: %d",
|
| + slot, occupier);
|
| + assert false;
|
| + } else {
|
| + mChildProcessConnections[slot] = null;
|
| + assert !mFreeConnectionIndices.contains(slot);
|
| + mFreeConnectionIndices.add(slot);
|
| + Log.d(TAG, "Allocator freed a connection, sandbox: %b, slot: %d", mInSandbox, slot);
|
| }
|
| + return mPendingSpawnQueue.poll();
|
| }
|
|
|
| public boolean isFreeConnectionAvailable() {
|
| - synchronized (mConnectionLock) {
|
| - return !mFreeConnectionIndices.isEmpty();
|
| - }
|
| + assert LauncherThread.runningOnLauncherThread();
|
| + return !mFreeConnectionIndices.isEmpty();
|
| }
|
|
|
| /** @return the count of connections managed by the allocator */
|
| @VisibleForTesting
|
| int allocatedConnectionsCountForTesting() {
|
| - synchronized (mConnectionLock) {
|
| - return mChildProcessConnections.length - mFreeConnectionIndices.size();
|
| - }
|
| + assert LauncherThread.runningOnLauncherThread();
|
| + return mChildProcessConnections.length - mFreeConnectionIndices.size();
|
| }
|
|
|
| @VisibleForTesting
|
| @@ -248,15 +234,13 @@ public class ChildConnectionAllocator {
|
|
|
| @VisibleForTesting
|
| void enqueuePendingQueueForTesting(ChildSpawnData spawnData) {
|
| - synchronized (mConnectionLock) {
|
| - mPendingSpawnQueue.add(spawnData);
|
| - }
|
| + assert LauncherThread.runningOnLauncherThread();
|
| + mPendingSpawnQueue.add(spawnData);
|
| }
|
|
|
| @VisibleForTesting
|
| int pendingSpawnsCountForTesting() {
|
| - synchronized (mConnectionLock) {
|
| - return mPendingSpawnQueue.size();
|
| - }
|
| + assert LauncherThread.runningOnLauncherThread();
|
| + return mPendingSpawnQueue.size();
|
| }
|
| }
|
|
|