| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
| 6 | 6 |
| 7 import android.content.ComponentName; | 7 import android.content.ComponentName; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.pm.ApplicationInfo; | 9 import android.content.pm.ApplicationInfo; |
| 10 import android.content.pm.PackageManager; | 10 import android.content.pm.PackageManager; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 // Map from package name to ChildConnectionAllocator. | 41 // Map from package name to ChildConnectionAllocator. |
| 42 private static Map<String, ChildConnectionAllocator> sSandboxedChildConnecti
onAllocatorMap; | 42 private static Map<String, ChildConnectionAllocator> sSandboxedChildConnecti
onAllocatorMap; |
| 43 | 43 |
| 44 // Allocator used for non-sandboxed services. | 44 // Allocator used for non-sandboxed services. |
| 45 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; | 45 private static ChildConnectionAllocator sPrivilegedChildConnectionAllocator; |
| 46 | 46 |
| 47 // Used by test to override the default sandboxed service settings. | 47 // Used by test to override the default sandboxed service settings. |
| 48 private static int sSandboxedServicesCountForTesting = -1; | 48 private static int sSandboxedServicesCountForTesting = -1; |
| 49 private static String sSandboxedServicesNameForTesting; | 49 private static String sSandboxedServicesNameForTesting; |
| 50 | 50 |
| 51 // The factory used to create BaseChildProcessConnection instances. |
| 52 private final BaseChildProcessConnection.Factory mConnectionFactory; |
| 53 |
| 51 // Connections to services. Indices of the array correspond to the service n
umbers. | 54 // Connections to services. Indices of the array correspond to the service n
umbers. |
| 52 private final ChildProcessConnection[] mChildProcessConnections; | 55 private final BaseChildProcessConnection[] mChildProcessConnections; |
| 53 | 56 |
| 54 private final String mChildClassName; | 57 private final String mChildClassName; |
| 55 private final boolean mInSandbox; | 58 private final boolean mInSandbox; |
| 56 | 59 |
| 57 // The list of free (not bound) service indices. | 60 // The list of free (not bound) service indices. |
| 58 private final ArrayList<Integer> mFreeConnectionIndices; | 61 private final ArrayList<Integer> mFreeConnectionIndices; |
| 59 | 62 |
| 60 // Each Allocator keeps a queue for the pending spawn data. Once a connectio
n is free, we | 63 // Each Allocator keeps a queue for the pending spawn data. Once a connectio
n is free, we |
| 61 // dequeue the pending spawn data from the same allocator as the connection. | 64 // dequeue the pending spawn data from the same allocator as the connection. |
| 62 private final Queue<ChildSpawnData> mPendingSpawnQueue = new LinkedList<>(); | 65 private final Queue<ChildSpawnData> mPendingSpawnQueue = new LinkedList<>(); |
| 63 | 66 |
| 64 @SuppressFBWarnings("LI_LAZY_INIT_STATIC") // Method is single thread. | 67 @SuppressFBWarnings("LI_LAZY_INIT_STATIC") // Method is single thread. |
| 65 public static ChildConnectionAllocator getAllocator( | 68 public static ChildConnectionAllocator getAllocator( |
| 66 Context context, String packageName, boolean inSandbox) { | 69 Context context, String packageName, boolean sandboxed) { |
| 67 assert LauncherThread.runningOnLauncherThread(); | 70 assert LauncherThread.runningOnLauncherThread(); |
| 68 if (!inSandbox) { | 71 if (!sandboxed) { |
| 69 if (sPrivilegedChildConnectionAllocator == null) { | 72 if (sPrivilegedChildConnectionAllocator == null) { |
| 70 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat
or(false, | 73 sPrivilegedChildConnectionAllocator = new ChildConnectionAllocat
or( |
| 74 ImportantChildProcessConnection.FACTORY, false /* sandbo
xed */, |
| 71 getNumberOfServices(context, false, packageName), | 75 getNumberOfServices(context, false, packageName), |
| 72 getClassNameOfService(context, false, packageName)); | 76 getClassNameOfService(context, false, packageName)); |
| 73 } | 77 } |
| 74 return sPrivilegedChildConnectionAllocator; | 78 return sPrivilegedChildConnectionAllocator; |
| 75 } | 79 } |
| 76 | 80 |
| 77 if (sSandboxedChildConnectionAllocatorMap == null) { | 81 if (sSandboxedChildConnectionAllocatorMap == null) { |
| 78 sSandboxedChildConnectionAllocatorMap = new HashMap<String, ChildCon
nectionAllocator>(); | 82 sSandboxedChildConnectionAllocatorMap = new HashMap<String, ChildCon
nectionAllocator>(); |
| 79 } | 83 } |
| 80 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageName)) { | 84 if (!sSandboxedChildConnectionAllocatorMap.containsKey(packageName)) { |
| 81 Log.w(TAG, | 85 Log.w(TAG, |
| 82 "Create a new ChildConnectionAllocator with package name = %
s," | 86 "Create a new ChildConnectionAllocator with package name = %
s," |
| 83 + " inSandbox = true", | 87 + " inSandbox = true", |
| 84 packageName); | 88 packageName); |
| 85 sSandboxedChildConnectionAllocatorMap.put(packageName, | 89 sSandboxedChildConnectionAllocatorMap.put(packageName, |
| 86 new ChildConnectionAllocator(true, | 90 new ChildConnectionAllocator(ManagedChildProcessConnection.F
ACTORY, |
| 87 getNumberOfServices(context, true, packageName), | 91 true /* sandboxed */, getNumberOfServices(context, t
rue, packageName), |
| 88 getClassNameOfService(context, true, packageName))); | 92 getClassNameOfService(context, true, packageName))); |
| 89 } | 93 } |
| 90 return sSandboxedChildConnectionAllocatorMap.get(packageName); | 94 return sSandboxedChildConnectionAllocatorMap.get(packageName); |
| 91 // TODO(pkotwicz|hanxi): Figure out when old allocators should be remove
d from | 95 // TODO(pkotwicz|hanxi): Figure out when old allocators should be remove
d from |
| 92 // {@code sSandboxedChildConnectionAllocatorMap}. | 96 // {@code sSandboxedChildConnectionAllocatorMap}. |
| 93 } | 97 } |
| 94 | 98 |
| 95 private static String getClassNameOfService( | 99 private static String getClassNameOfService( |
| 96 Context context, boolean inSandbox, String packageName) { | 100 Context context, boolean inSandbox, String packageName) { |
| 97 if (!inSandbox) { | 101 if (!inSandbox) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 } | 157 } |
| 154 return numServices; | 158 return numServices; |
| 155 } | 159 } |
| 156 | 160 |
| 157 @VisibleForTesting | 161 @VisibleForTesting |
| 158 public static void setSandboxServicesSettingsForTesting(int serviceCount, St
ring serviceName) { | 162 public static void setSandboxServicesSettingsForTesting(int serviceCount, St
ring serviceName) { |
| 159 sSandboxedServicesCountForTesting = serviceCount; | 163 sSandboxedServicesCountForTesting = serviceCount; |
| 160 sSandboxedServicesNameForTesting = serviceName; | 164 sSandboxedServicesNameForTesting = serviceName; |
| 161 } | 165 } |
| 162 | 166 |
| 163 private ChildConnectionAllocator( | 167 private ChildConnectionAllocator(BaseChildProcessConnection.Factory connecti
onFactory, |
| 164 boolean inSandbox, int numChildServices, String serviceClassName) { | 168 boolean inSandbox, int numChildServices, String serviceClassName) { |
| 165 mChildProcessConnections = new ChildProcessConnectionImpl[numChildServic
es]; | 169 mConnectionFactory = connectionFactory; |
| 170 mChildProcessConnections = new BaseChildProcessConnection[numChildServic
es]; |
| 166 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); | 171 mFreeConnectionIndices = new ArrayList<Integer>(numChildServices); |
| 167 for (int i = 0; i < numChildServices; i++) { | 172 for (int i = 0; i < numChildServices; i++) { |
| 168 mFreeConnectionIndices.add(i); | 173 mFreeConnectionIndices.add(i); |
| 169 } | 174 } |
| 170 mChildClassName = serviceClassName; | 175 mChildClassName = serviceClassName; |
| 171 mInSandbox = inSandbox; | 176 mInSandbox = inSandbox; |
| 172 } | 177 } |
| 173 | 178 |
| 174 // Allocates or enqueues. If there are no free slots, returns null and enque
ues the spawn data. | 179 // Allocates or enqueues. If there are no free slots, returns null and enque
ues the spawn data. |
| 175 public ChildProcessConnection allocate(ChildSpawnData spawnData, | 180 public BaseChildProcessConnection allocate(ChildSpawnData spawnData, |
| 176 ChildProcessConnection.DeathCallback deathCallback, Bundle childProc
essCommonParameters, | 181 BaseChildProcessConnection.DeathCallback deathCallback, |
| 177 boolean queueIfNoSlotAvailable) { | 182 Bundle childProcessCommonParameters, boolean queueIfNoSlotAvailable)
{ |
| 178 assert LauncherThread.runningOnLauncherThread(); | 183 assert LauncherThread.runningOnLauncherThread(); |
| 179 assert spawnData.isInSandbox() == mInSandbox; | 184 assert spawnData.isInSandbox() == mInSandbox; |
| 180 if (mFreeConnectionIndices.isEmpty()) { | 185 if (mFreeConnectionIndices.isEmpty()) { |
| 181 Log.d(TAG, "Ran out of services to allocate."); | 186 Log.d(TAG, "Ran out of services to allocate."); |
| 182 if (queueIfNoSlotAvailable) { | 187 if (queueIfNoSlotAvailable) { |
| 183 mPendingSpawnQueue.add(spawnData); | 188 mPendingSpawnQueue.add(spawnData); |
| 184 } | 189 } |
| 185 return null; | 190 return null; |
| 186 } | 191 } |
| 187 int slot = mFreeConnectionIndices.remove(0); | 192 int slot = mFreeConnectionIndices.remove(0); |
| 188 assert mChildProcessConnections[slot] == null; | 193 assert mChildProcessConnections[slot] == null; |
| 189 mChildProcessConnections[slot] = new ChildProcessConnectionImpl(spawnDat
a.getContext(), | 194 mChildProcessConnections[slot] = mConnectionFactory.create(spawnData.get
Context(), slot, |
| 190 slot, mInSandbox, deathCallback, mChildClassName, childProcessCo
mmonParameters, | 195 mInSandbox, deathCallback, mChildClassName, childProcessCommonPa
rameters, |
| 191 spawnData.isAlwaysInForeground(), spawnData.getCreationParams())
; | 196 spawnData.getCreationParams()); |
| 192 Log.d(TAG, "Allocator allocated a connection, sandbox: %b, slot: %d", mI
nSandbox, slot); | 197 Log.d(TAG, "Allocator allocated a connection, sandbox: %b, slot: %d", mI
nSandbox, slot); |
| 193 return mChildProcessConnections[slot]; | 198 return mChildProcessConnections[slot]; |
| 194 } | 199 } |
| 195 | 200 |
| 196 // Also return the first ChildSpawnData in the pending queue, if any. | 201 // Also return the first ChildSpawnData in the pending queue, if any. |
| 197 public ChildSpawnData free(ChildProcessConnection connection) { | 202 public ChildSpawnData free(BaseChildProcessConnection connection) { |
| 198 assert LauncherThread.runningOnLauncherThread(); | 203 assert LauncherThread.runningOnLauncherThread(); |
| 199 int slot = connection.getServiceNumber(); | 204 int slot = connection.getServiceNumber(); |
| 200 if (mChildProcessConnections[slot] != connection) { | 205 if (mChildProcessConnections[slot] != connection) { |
| 201 int occupier = mChildProcessConnections[slot] == null | 206 int occupier = mChildProcessConnections[slot] == null |
| 202 ? -1 | 207 ? -1 |
| 203 : mChildProcessConnections[slot].getServiceNumber(); | 208 : mChildProcessConnections[slot].getServiceNumber(); |
| 204 Log.e(TAG, | 209 Log.e(TAG, |
| 205 "Unable to find connection to free in slot: %d " | 210 "Unable to find connection to free in slot: %d " |
| 206 + "already occupied by service: %d", | 211 + "already occupied by service: %d", |
| 207 slot, occupier); | 212 slot, occupier); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 221 } | 226 } |
| 222 | 227 |
| 223 /** @return the count of connections managed by the allocator */ | 228 /** @return the count of connections managed by the allocator */ |
| 224 @VisibleForTesting | 229 @VisibleForTesting |
| 225 int allocatedConnectionsCountForTesting() { | 230 int allocatedConnectionsCountForTesting() { |
| 226 assert LauncherThread.runningOnLauncherThread(); | 231 assert LauncherThread.runningOnLauncherThread(); |
| 227 return mChildProcessConnections.length - mFreeConnectionIndices.size(); | 232 return mChildProcessConnections.length - mFreeConnectionIndices.size(); |
| 228 } | 233 } |
| 229 | 234 |
| 230 @VisibleForTesting | 235 @VisibleForTesting |
| 231 ChildProcessConnection[] connectionArrayForTesting() { | 236 BaseChildProcessConnection[] connectionArrayForTesting() { |
| 232 return mChildProcessConnections; | 237 return mChildProcessConnections; |
| 233 } | 238 } |
| 234 | 239 |
| 235 @VisibleForTesting | 240 @VisibleForTesting |
| 236 void enqueuePendingQueueForTesting(ChildSpawnData spawnData) { | 241 void enqueuePendingQueueForTesting(ChildSpawnData spawnData) { |
| 237 assert LauncherThread.runningOnLauncherThread(); | 242 assert LauncherThread.runningOnLauncherThread(); |
| 238 mPendingSpawnQueue.add(spawnData); | 243 mPendingSpawnQueue.add(spawnData); |
| 239 } | 244 } |
| 240 | 245 |
| 241 @VisibleForTesting | 246 @VisibleForTesting |
| 242 int pendingSpawnsCountForTesting() { | 247 int pendingSpawnsCountForTesting() { |
| 243 assert LauncherThread.runningOnLauncherThread(); | 248 assert LauncherThread.runningOnLauncherThread(); |
| 244 return mPendingSpawnQueue.size(); | 249 return mPendingSpawnQueue.size(); |
| 245 } | 250 } |
| 246 } | 251 } |
| OLD | NEW |