OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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.TargetApi; | 7 import android.annotation.TargetApi; |
8 import android.content.ComponentCallbacks2; | 8 import android.content.ComponentCallbacks2; |
9 import android.content.Context; | 9 import android.content.Context; |
10 import android.content.res.Configuration; | 10 import android.content.res.Configuration; |
11 import android.os.Build; | 11 import android.os.Build; |
12 import android.os.Handler; | 12 import android.os.Handler; |
13 import android.util.LruCache; | 13 import android.util.LruCache; |
14 import android.util.SparseArray; | 14 import android.util.SparseArray; |
15 | 15 |
16 import org.chromium.base.Log; | 16 import org.chromium.base.Log; |
17 import org.chromium.base.SysUtils; | 17 import org.chromium.base.SysUtils; |
18 import org.chromium.base.ThreadUtils; | 18 import org.chromium.base.ThreadUtils; |
19 import org.chromium.base.VisibleForTesting; | 19 import org.chromium.base.VisibleForTesting; |
20 import org.chromium.base.metrics.RecordHistogram; | 20 import org.chromium.base.metrics.RecordHistogram; |
21 | 21 |
22 import java.util.Map; | 22 import java.util.Map; |
23 import java.util.concurrent.atomic.AtomicReference; | 23 import java.util.concurrent.atomic.AtomicReference; |
24 | 24 |
| 25 import javax.annotation.concurrent.GuardedBy; |
| 26 |
25 /** | 27 /** |
26 * Manages oom bindings used to bound child services. | 28 * Manages oom bindings used to bound child services. |
27 */ | 29 */ |
28 class BindingManagerImpl implements BindingManager { | 30 class BindingManagerImpl implements BindingManager { |
29 private static final String TAG = "cr.BindingManager"; | 31 private static final String TAG = "cr.BindingManager"; |
30 | 32 |
31 // Low reduce ratio of moderate binding. | 33 // Low reduce ratio of moderate binding. |
32 private static final float MODERATE_BINDING_LOW_REDUCE_RATIO = 0.25f; | 34 private static final float MODERATE_BINDING_LOW_REDUCE_RATIO = 0.25f; |
33 // High reduce ratio of moderate binding. | 35 // High reduce ratio of moderate binding. |
34 private static final float MODERATE_BINDING_HIGH_REDUCE_RATIO = 0.5f; | 36 private static final float MODERATE_BINDING_HIGH_REDUCE_RATIO = 0.5f; |
35 | 37 |
36 // Delay of 1 second used when removing temporary strong binding of a proces
s (only on | 38 // Delay of 1 second used when removing temporary strong binding of a proces
s (only on |
37 // non-low-memory devices). | 39 // non-low-memory devices). |
38 private static final long DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS = 1 * 1000; | 40 private static final long DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS = 1 * 1000; |
39 | 41 |
40 // Delays used when clearing moderate binding pool when onSentToBackground h
appens. | 42 // Delays used when clearing moderate binding pool when onSentToBackground h
appens. |
41 private static final long MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS = 10 *
1000; | 43 private static final long MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS = 10 *
1000; |
42 | 44 |
43 // These fields allow to override the parameters for testing - see | 45 // These fields allow to override the parameters for testing - see |
44 // createBindingManagerForTesting(). | 46 // createBindingManagerForTesting(). |
45 private final boolean mIsLowMemoryDevice; | 47 private final boolean mIsLowMemoryDevice; |
46 | 48 |
47 private static class ModerateBindingPool | 49 private static class ModerateBindingPool |
48 extends LruCache<Integer, ManagedConnection> implements ComponentCal
lbacks2 { | 50 extends LruCache<Integer, ManagedConnection> implements ComponentCal
lbacks2 { |
49 private final Object mDelayedClearerLock = new Object(); | 51 private final Object mDelayedClearerLock = new Object(); |
| 52 |
| 53 @GuardedBy("mDelayedClearerLock") |
50 private Runnable mDelayedClearer; | 54 private Runnable mDelayedClearer; |
| 55 |
51 private final Handler mHandler = new Handler(ThreadUtils.getUiThreadLoop
er()); | 56 private final Handler mHandler = new Handler(ThreadUtils.getUiThreadLoop
er()); |
52 | 57 |
53 public ModerateBindingPool(int maxSize) { | 58 public ModerateBindingPool(int maxSize) { |
54 super(maxSize); | 59 super(maxSize); |
55 } | 60 } |
56 | 61 |
57 @Override | 62 @Override |
58 public void onTrimMemory(int level) { | 63 public void onTrimMemory(int level) { |
59 Log.i(TAG, "onTrimMemory: level=%d, size=%d", level, size()); | 64 Log.i(TAG, "onTrimMemory: level=%d, size=%d", level, size()); |
60 if (size() > 0) { | 65 if (size() > 0) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 int count = 0; | 100 int count = 0; |
96 for (Map.Entry<Integer, ManagedConnection> entry : snapshot().en
trySet()) { | 101 for (Map.Entry<Integer, ManagedConnection> entry : snapshot().en
trySet()) { |
97 remove(entry.getKey()); | 102 remove(entry.getKey()); |
98 ++count; | 103 ++count; |
99 if (count == oldSize - newSize) break; | 104 if (count == oldSize - newSize) break; |
100 } | 105 } |
101 } | 106 } |
102 } | 107 } |
103 | 108 |
104 void addConnection(ManagedConnection managedConnection) { | 109 void addConnection(ManagedConnection managedConnection) { |
105 ChildProcessConnection connection = managedConnection.mConnection; | 110 ManagedChildProcessConnection connection = managedConnection.mConnec
tion; |
106 if (connection != null && connection.isInSandbox()) { | 111 if (connection != null && connection.isSandboxed()) { |
107 managedConnection.addModerateBinding(); | 112 managedConnection.addModerateBinding(); |
108 if (connection.isModerateBindingBound()) { | 113 if (connection.isModerateBindingBound()) { |
109 put(connection.getServiceNumber(), managedConnection); | 114 put(connection.getServiceNumber(), managedConnection); |
110 } else { | 115 } else { |
111 remove(connection.getServiceNumber()); | 116 remove(connection.getServiceNumber()); |
112 } | 117 } |
113 } | 118 } |
114 } | 119 } |
115 | 120 |
116 void removeConnection(ManagedConnection managedConnection) { | 121 void removeConnection(ManagedConnection managedConnection) { |
117 ChildProcessConnection connection = managedConnection.mConnection; | 122 ManagedChildProcessConnection connection = managedConnection.mConnec
tion; |
118 if (connection != null && connection.isInSandbox()) { | 123 if (connection != null && connection.isSandboxed()) { |
119 remove(connection.getServiceNumber()); | 124 remove(connection.getServiceNumber()); |
120 } | 125 } |
121 } | 126 } |
122 | 127 |
123 @Override | 128 @Override |
124 protected void entryRemoved(boolean evicted, Integer key, ManagedConnect
ion oldValue, | 129 protected void entryRemoved(boolean evicted, Integer key, ManagedConnect
ion oldValue, |
125 ManagedConnection newValue) { | 130 ManagedConnection newValue) { |
126 if (oldValue != newValue) { | 131 if (oldValue != newValue) { |
127 oldValue.removeModerateBinding(); | 132 oldValue.removeModerateBinding(); |
128 } | 133 } |
(...skipping 27 matching lines...) Expand all Loading... |
156 mHandler.removeCallbacks(mDelayedClearer); | 161 mHandler.removeCallbacks(mDelayedClearer); |
157 mDelayedClearer = null; | 162 mDelayedClearer = null; |
158 } | 163 } |
159 } | 164 } |
160 } | 165 } |
161 | 166 |
162 private final AtomicReference<ModerateBindingPool> mModerateBindingPool = | 167 private final AtomicReference<ModerateBindingPool> mModerateBindingPool = |
163 new AtomicReference<>(); | 168 new AtomicReference<>(); |
164 | 169 |
165 /** | 170 /** |
166 * Wraps ChildProcessConnection keeping track of additional information need
ed to manage the | 171 * Wraps ManagedChildProcessConnection keeping track of additional informati
on needed to manage |
167 * bindings of the connection. The reference to ChildProcessConnection is cl
eared when the | 172 * the bindings of the connection. The reference to ManagedChildProcessConne
ction is cleared |
168 * connection goes away, but ManagedConnection itself is kept (until overwri
tten by a new entry | 173 * when the connection goes away, but ManagedConnection itself is kept (unti
l overwritten by a |
169 * for the same pid). | 174 * new entry for the same pid). |
170 */ | 175 */ |
171 private class ManagedConnection { | 176 private class ManagedConnection { |
172 // Set in constructor, cleared in clearConnection() (on a separate threa
d). | 177 // Set in constructor, cleared in clearConnection() (on a separate threa
d). |
173 // Need to keep a local reference to avoid it being cleared while using
it. | 178 // Need to keep a local reference to avoid it being cleared while using
it. |
174 private ChildProcessConnection mConnection; | 179 private ManagedChildProcessConnection mConnection; |
175 | 180 |
176 // True iff there is a strong binding kept on the service because it is
working in | 181 // True iff there is a strong binding kept on the service because it is
working in |
177 // foreground. | 182 // foreground. |
178 private boolean mInForeground; | 183 private boolean mInForeground; |
179 | 184 |
180 // True iff there is a strong binding kept on the service because it was
bound for the | 185 // True iff there is a strong binding kept on the service because it was
bound for the |
181 // application background period. | 186 // application background period. |
182 private boolean mBoundForBackgroundPeriod; | 187 private boolean mBoundForBackgroundPeriod; |
183 | 188 |
184 // When mConnection is cleared, oom binding status is stashed here. | |
185 private boolean mWasOomProtected; | |
186 | |
187 /** | 189 /** |
188 * Removes the initial service binding. | 190 * Removes the initial service binding. |
189 * @return true if the binding was removed. | 191 * @return true if the binding was removed. |
190 */ | 192 */ |
191 private boolean removeInitialBinding() { | 193 private boolean removeInitialBinding() { |
192 ChildProcessConnection connection = mConnection; | 194 ManagedChildProcessConnection connection = mConnection; |
193 if (connection == null || !connection.isInitialBindingBound()) retur
n false; | 195 if (connection == null || !connection.isInitialBindingBound()) retur
n false; |
194 | 196 |
195 connection.removeInitialBinding(); | 197 connection.removeInitialBinding(); |
196 return true; | 198 return true; |
197 } | 199 } |
198 | 200 |
199 /** Adds a strong service binding. */ | 201 /** Adds a strong service binding. */ |
200 private void addStrongBinding() { | 202 private void addStrongBinding() { |
201 ChildProcessConnection connection = mConnection; | 203 ManagedChildProcessConnection connection = mConnection; |
202 if (connection == null) return; | 204 if (connection == null) return; |
203 | 205 |
204 connection.addStrongBinding(); | 206 connection.addStrongBinding(); |
205 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get()
; | 207 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get()
; |
206 if (moderateBindingPool != null) moderateBindingPool.removeConnectio
n(this); | 208 if (moderateBindingPool != null) moderateBindingPool.removeConnectio
n(this); |
207 } | 209 } |
208 | 210 |
209 /** Removes a strong service binding. */ | 211 /** Removes a strong service binding. */ |
210 private void removeStrongBinding(final boolean keepAsModerate) { | 212 private void removeStrongBinding(final boolean keepAsModerate) { |
211 final ChildProcessConnection connection = mConnection; | 213 final ManagedChildProcessConnection connection = mConnection; |
212 // We have to fail gracefully if the strong binding is not present,
as on low-end the | 214 // We have to fail gracefully if the strong binding is not present,
as on low-end the |
213 // binding could have been removed by dropOomBindings() when a new s
ervice was started. | 215 // binding could have been removed by dropOomBindings() when a new s
ervice was started. |
214 if (connection == null || !connection.isStrongBindingBound()) return
; | 216 if (connection == null || !connection.isStrongBindingBound()) return
; |
215 | 217 |
216 // This runnable performs the actual unbinding. It will be executed
synchronously when | 218 // This runnable performs the actual unbinding. It will be executed
synchronously when |
217 // on low-end devices and posted with a delay otherwise. | 219 // on low-end devices and posted with a delay otherwise. |
218 Runnable doUnbind = new Runnable() { | 220 Runnable doUnbind = new Runnable() { |
219 @Override | 221 @Override |
220 public void run() { | 222 public void run() { |
221 if (connection.isStrongBindingBound()) { | 223 if (connection.isStrongBindingBound()) { |
(...skipping 10 matching lines...) Expand all Loading... |
232 } else { | 234 } else { |
233 ThreadUtils.postOnUiThreadDelayed(doUnbind, DETACH_AS_ACTIVE_HIG
H_END_DELAY_MILLIS); | 235 ThreadUtils.postOnUiThreadDelayed(doUnbind, DETACH_AS_ACTIVE_HIG
H_END_DELAY_MILLIS); |
234 } | 236 } |
235 } | 237 } |
236 | 238 |
237 /** | 239 /** |
238 * Adds connection to the moderate binding pool. No-op if the connection
has a strong | 240 * Adds connection to the moderate binding pool. No-op if the connection
has a strong |
239 * binding. | 241 * binding. |
240 * @param connection The ChildProcessConnection to add to the moderate b
inding pool. | 242 * @param connection The ChildProcessConnection to add to the moderate b
inding pool. |
241 */ | 243 */ |
242 private void addConnectionToModerateBindingPool(ChildProcessConnection c
onnection) { | 244 private void addConnectionToModerateBindingPool(ManagedChildProcessConne
ction connection) { |
243 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get()
; | 245 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get()
; |
244 if (moderateBindingPool != null && !connection.isStrongBindingBound(
)) { | 246 if (moderateBindingPool != null && !connection.isStrongBindingBound(
)) { |
245 moderateBindingPool.addConnection(ManagedConnection.this); | 247 moderateBindingPool.addConnection(ManagedConnection.this); |
246 } | 248 } |
247 } | 249 } |
248 | 250 |
249 /** Removes the moderate service binding. */ | 251 /** Removes the moderate service binding. */ |
250 private void removeModerateBinding() { | 252 private void removeModerateBinding() { |
251 ChildProcessConnection connection = mConnection; | 253 ManagedChildProcessConnection connection = mConnection; |
252 if (connection == null || !connection.isModerateBindingBound()) retu
rn; | 254 if (connection == null || !connection.isModerateBindingBound()) retu
rn; |
253 | |
254 connection.removeModerateBinding(); | 255 connection.removeModerateBinding(); |
255 } | 256 } |
256 | 257 |
257 /** Adds the moderate service binding. */ | 258 /** Adds the moderate service binding. */ |
258 private void addModerateBinding() { | 259 private void addModerateBinding() { |
259 ChildProcessConnection connection = mConnection; | 260 ManagedChildProcessConnection connection = mConnection; |
260 if (connection == null) return; | 261 if (connection == null) return; |
261 | 262 |
262 connection.addModerateBinding(); | 263 connection.addModerateBinding(); |
263 } | 264 } |
264 | 265 |
265 /** | 266 /** |
266 * Drops the service bindings. This is used on low-end to drop bindings
of the current | 267 * Drops the service bindings. This is used on low-end to drop bindings
of the current |
267 * service when a new one is used in foreground. | 268 * service when a new one is used in foreground. |
268 */ | 269 */ |
269 private void dropBindings() { | 270 private void dropBindings() { |
270 assert mIsLowMemoryDevice; | 271 assert mIsLowMemoryDevice; |
271 ChildProcessConnection connection = mConnection; | 272 ManagedChildProcessConnection connection = mConnection; |
272 if (connection == null) return; | 273 if (connection == null) return; |
273 | 274 |
274 connection.dropOomBindings(); | 275 connection.dropOomBindings(); |
275 } | 276 } |
276 | 277 |
277 ManagedConnection(ChildProcessConnection connection) { | 278 ManagedConnection(ManagedChildProcessConnection connection) { |
278 mConnection = connection; | 279 mConnection = connection; |
279 } | 280 } |
280 | 281 |
281 /** | 282 /** |
282 * Sets the visibility of the service, adding or removing the strong bin
ding as needed. | 283 * Sets the visibility of the service, adding or removing the strong bin
ding as needed. |
283 */ | 284 */ |
284 void setInForeground(boolean nextInForeground) { | 285 void setInForeground(boolean nextInForeground) { |
285 if (!mInForeground && nextInForeground) { | 286 if (!mInForeground && nextInForeground) { |
286 addStrongBinding(); | 287 addStrongBinding(); |
287 } else if (mInForeground && !nextInForeground) { | 288 } else if (mInForeground && !nextInForeground) { |
(...skipping 20 matching lines...) Expand all Loading... |
308 void setBoundForBackgroundPeriod(boolean nextBound) { | 309 void setBoundForBackgroundPeriod(boolean nextBound) { |
309 if (!mBoundForBackgroundPeriod && nextBound) { | 310 if (!mBoundForBackgroundPeriod && nextBound) { |
310 addStrongBinding(); | 311 addStrongBinding(); |
311 } else if (mBoundForBackgroundPeriod && !nextBound) { | 312 } else if (mBoundForBackgroundPeriod && !nextBound) { |
312 removeStrongBinding(false); | 313 removeStrongBinding(false); |
313 } | 314 } |
314 | 315 |
315 mBoundForBackgroundPeriod = nextBound; | 316 mBoundForBackgroundPeriod = nextBound; |
316 } | 317 } |
317 | 318 |
318 boolean isOomProtected() { | |
319 // When a process crashes, we can be queried about its oom status be
fore or after the | |
320 // connection is cleared. For the latter case, the oom status is sta
shed in | |
321 // mWasOomProtected. | |
322 ChildProcessConnection connection = mConnection; | |
323 return connection != null | |
324 ? connection.isOomProtectedOrWasWhenDied() : mWasOomProtecte
d; | |
325 } | |
326 | |
327 void clearConnection() { | 319 void clearConnection() { |
328 mWasOomProtected = mConnection.isOomProtectedOrWasWhenDied(); | |
329 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get()
; | 320 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get()
; |
330 if (moderateBindingPool != null) moderateBindingPool.removeConnectio
n(this); | 321 if (moderateBindingPool != null) moderateBindingPool.removeConnectio
n(this); |
331 mConnection = null; | 322 mConnection = null; |
332 } | 323 } |
333 | |
334 /** @return true iff the reference to the connection is no longer held *
/ | |
335 @VisibleForTesting | |
336 boolean isConnectionCleared() { | |
337 return mConnection == null; | |
338 } | |
339 } | 324 } |
340 | 325 |
341 // This can be manipulated on different threads, synchronize access on mMana
gedConnections. | 326 // This can be manipulated on different threads, synchronize access on mMana
gedConnections. |
342 private final SparseArray<ManagedConnection> mManagedConnections = | 327 private final SparseArray<ManagedConnection> mManagedConnections = |
343 new SparseArray<ManagedConnection>(); | 328 new SparseArray<ManagedConnection>(); |
344 | 329 |
345 // The connection that was most recently set as foreground (using setInForeg
round()). This is | 330 // The connection that was most recently set as foreground (using setInForeg
round()). This is |
346 // used to add additional binding on it when the embedder goes to background
. On low-end, this | 331 // used to add additional binding on it when the embedder goes to background
. On low-end, this |
347 // is also used to drop process bidnings when a new one is created, making s
ure that only one | 332 // is also used to drop process bidnings when a new one is created, making s
ure that only one |
348 // renderer process at a time is protected from oom killing. | 333 // renderer process at a time is protected from oom killing. |
(...skipping 25 matching lines...) Expand all Loading... |
374 /** | 359 /** |
375 * Creates a testing instance of BindingManager. Testing instance will have
the unbinding delays | 360 * Creates a testing instance of BindingManager. Testing instance will have
the unbinding delays |
376 * set to 0, so that the tests don't need to deal with actual waiting. | 361 * set to 0, so that the tests don't need to deal with actual waiting. |
377 * @param isLowEndDevice true iff the created instance should apply low-end
binding policies | 362 * @param isLowEndDevice true iff the created instance should apply low-end
binding policies |
378 */ | 363 */ |
379 public static BindingManagerImpl createBindingManagerForTesting(boolean isLo
wEndDevice) { | 364 public static BindingManagerImpl createBindingManagerForTesting(boolean isLo
wEndDevice) { |
380 return new BindingManagerImpl(isLowEndDevice, true); | 365 return new BindingManagerImpl(isLowEndDevice, true); |
381 } | 366 } |
382 | 367 |
383 @Override | 368 @Override |
384 public void addNewConnection(int pid, ChildProcessConnection connection) { | 369 public void addNewConnection(int pid, ManagedChildProcessConnection connecti
on) { |
385 // This will reset the previous entry for the pid in the unlikely event
of the OS | 370 // This will reset the previous entry for the pid in the unlikely event
of the OS |
386 // reusing renderer pids. | 371 // reusing renderer pids. |
387 synchronized (mManagedConnections) { | 372 synchronized (mManagedConnections) { |
388 mManagedConnections.put(pid, new ManagedConnection(connection)); | 373 mManagedConnections.put(pid, new ManagedConnection(connection)); |
389 } | 374 } |
390 } | 375 } |
391 | 376 |
392 @Override | 377 @Override |
393 public void setInForeground(int pid, boolean inForeground) { | 378 public void setInForeground(int pid, boolean inForeground) { |
394 ManagedConnection managedConnection; | 379 ManagedConnection managedConnection; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 public void onBroughtToForeground() { | 432 public void onBroughtToForeground() { |
448 if (mBoundForBackgroundPeriod != null) { | 433 if (mBoundForBackgroundPeriod != null) { |
449 mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false); | 434 mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false); |
450 mBoundForBackgroundPeriod = null; | 435 mBoundForBackgroundPeriod = null; |
451 } | 436 } |
452 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); | 437 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); |
453 if (moderateBindingPool != null) moderateBindingPool.onBroughtToForegrou
nd(); | 438 if (moderateBindingPool != null) moderateBindingPool.onBroughtToForegrou
nd(); |
454 } | 439 } |
455 | 440 |
456 @Override | 441 @Override |
457 public boolean isOomProtected(int pid) { | 442 public void removeConnection(int pid) { |
458 // In the unlikely event of the OS reusing renderer pid, the call will r
efer to the most | |
459 // recent renderer of the given pid. The binding state for a pid is bein
g reset in | |
460 // addNewConnection(). | |
461 ManagedConnection managedConnection; | 443 ManagedConnection managedConnection; |
462 synchronized (mManagedConnections) { | 444 synchronized (mManagedConnections) { |
463 managedConnection = mManagedConnections.get(pid); | 445 managedConnection = mManagedConnections.get(pid); |
| 446 if (managedConnection != null) { |
| 447 mManagedConnections.remove(pid); |
| 448 } |
464 } | 449 } |
465 return managedConnection != null ? managedConnection.isOomProtected() :
false; | 450 if (managedConnection != null) { |
466 } | 451 managedConnection.clearConnection(); |
467 | |
468 @Override | |
469 public void clearConnection(int pid) { | |
470 ManagedConnection managedConnection; | |
471 synchronized (mManagedConnections) { | |
472 managedConnection = mManagedConnections.get(pid); | |
473 } | 452 } |
474 if (managedConnection != null) managedConnection.clearConnection(); | |
475 } | 453 } |
476 | 454 |
477 /** @return true iff the connection reference is no longer held */ | 455 /** @return true iff the connection reference is no longer held */ |
478 @VisibleForTesting | 456 @VisibleForTesting |
479 public boolean isConnectionCleared(int pid) { | 457 public boolean isConnectionCleared(int pid) { |
480 synchronized (mManagedConnections) { | 458 synchronized (mManagedConnections) { |
481 return mManagedConnections.get(pid).isConnectionCleared(); | 459 return mManagedConnections.get(pid) == null; |
482 } | 460 } |
483 } | 461 } |
484 | 462 |
485 @Override | 463 @Override |
486 public void startModerateBindingManagement(Context context, int maxSize) { | 464 public void startModerateBindingManagement(Context context, int maxSize) { |
487 if (mIsLowMemoryDevice) return; | 465 if (mIsLowMemoryDevice) return; |
488 ModerateBindingPool pool = new ModerateBindingPool(maxSize); | 466 ModerateBindingPool pool = new ModerateBindingPool(maxSize); |
489 if (mModerateBindingPool.compareAndSet(null, pool)) { | 467 if (mModerateBindingPool.compareAndSet(null, pool)) { |
490 Log.i(TAG, "Moderate binding enabled: maxSize=%d", maxSize); | 468 Log.i(TAG, "Moderate binding enabled: maxSize=%d", maxSize); |
491 if (context != null) context.registerComponentCallbacks(pool); | 469 if (context != null) context.registerComponentCallbacks(pool); |
492 } | 470 } |
493 } | 471 } |
494 | 472 |
495 @Override | 473 @Override |
496 public void releaseAllModerateBindings() { | 474 public void releaseAllModerateBindings() { |
497 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); | 475 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); |
498 if (moderateBindingPool != null) { | 476 if (moderateBindingPool != null) { |
499 Log.i(TAG, "Release all moderate bindings: %d", moderateBindingPool.
size()); | 477 Log.i(TAG, "Release all moderate bindings: %d", moderateBindingPool.
size()); |
500 moderateBindingPool.evictAll(); | 478 moderateBindingPool.evictAll(); |
501 } | 479 } |
502 } | 480 } |
503 } | 481 } |
OLD | NEW |