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) { |
61 if (level <= TRIM_MEMORY_RUNNING_MODERATE) { | 66 if (level <= TRIM_MEMORY_RUNNING_MODERATE) { |
62 reduce(MODERATE_BINDING_LOW_REDUCE_RATIO); | 67 reduce(MODERATE_BINDING_LOW_REDUCE_RATIO); |
63 } else if (level <= TRIM_MEMORY_RUNNING_LOW) { | 68 } else if (level <= TRIM_MEMORY_RUNNING_LOW) { |
64 reduce(MODERATE_BINDING_HIGH_REDUCE_RATIO); | 69 reduce(MODERATE_BINDING_HIGH_REDUCE_RATIO); |
65 } else if (level == TRIM_MEMORY_UI_HIDDEN) { | 70 } else if (level == TRIM_MEMORY_UI_HIDDEN) { |
66 // This will be handled by |mDelayedClearer|. | 71 // This will be handled by |mDelayedClearer |
boliu
2017/04/20 22:33:34
what happened to this comment?
Jay Civelli
2017/04/25 06:02:46
Fixed.
| |
67 return; | 72 return; |
68 } else { | 73 } else { |
69 evictAll(); | 74 evictAll(); |
70 } | 75 } |
71 } | 76 } |
72 } | 77 } |
73 | 78 |
74 @Override | 79 @Override |
75 public void onLowMemory() { | 80 public void onLowMemory() { |
76 Log.i(TAG, "onLowMemory: evict %d bindings", size()); | 81 Log.i(TAG, "onLowMemory: evict %d bindings", size()); |
(...skipping 18 matching lines...) Expand all 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 | 324 |
334 /** @return true iff the reference to the connection is no longer held * / | 325 /** @return true iff the reference to the connection is no longer held * / |
335 @VisibleForTesting | 326 @VisibleForTesting |
336 boolean isConnectionCleared() { | 327 boolean isConnectionCleared() { |
337 return mConnection == null; | 328 return mConnection == null; |
338 } | 329 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
374 /** | 365 /** |
375 * Creates a testing instance of BindingManager. Testing instance will have the unbinding delays | 366 * 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. | 367 * 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 | 368 * @param isLowEndDevice true iff the created instance should apply low-end binding policies |
378 */ | 369 */ |
379 public static BindingManagerImpl createBindingManagerForTesting(boolean isLo wEndDevice) { | 370 public static BindingManagerImpl createBindingManagerForTesting(boolean isLo wEndDevice) { |
380 return new BindingManagerImpl(isLowEndDevice, true); | 371 return new BindingManagerImpl(isLowEndDevice, true); |
381 } | 372 } |
382 | 373 |
383 @Override | 374 @Override |
384 public void addNewConnection(int pid, ChildProcessConnection connection) { | 375 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 | 376 // This will reset the previous entry for the pid in the unlikely event of the OS |
386 // reusing renderer pids. | 377 // reusing renderer pids. |
387 synchronized (mManagedConnections) { | 378 synchronized (mManagedConnections) { |
388 mManagedConnections.put(pid, new ManagedConnection(connection)); | 379 mManagedConnections.put(pid, new ManagedConnection(connection)); |
389 } | 380 } |
390 } | 381 } |
391 | 382 |
392 @Override | 383 @Override |
393 public void setInForeground(int pid, boolean inForeground) { | 384 public void setInForeground(int pid, boolean inForeground) { |
394 ManagedConnection managedConnection; | 385 ManagedConnection managedConnection; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
447 public void onBroughtToForeground() { | 438 public void onBroughtToForeground() { |
448 if (mBoundForBackgroundPeriod != null) { | 439 if (mBoundForBackgroundPeriod != null) { |
449 mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false); | 440 mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false); |
450 mBoundForBackgroundPeriod = null; | 441 mBoundForBackgroundPeriod = null; |
451 } | 442 } |
452 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); | 443 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); |
453 if (moderateBindingPool != null) moderateBindingPool.onBroughtToForegrou nd(); | 444 if (moderateBindingPool != null) moderateBindingPool.onBroughtToForegrou nd(); |
454 } | 445 } |
455 | 446 |
456 @Override | 447 @Override |
457 public boolean isOomProtected(int pid) { | 448 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; | 449 ManagedConnection managedConnection; |
462 synchronized (mManagedConnections) { | 450 synchronized (mManagedConnections) { |
463 managedConnection = mManagedConnections.get(pid); | 451 managedConnection = mManagedConnections.get(pid); |
452 if (managedConnection != null) { | |
453 mManagedConnections.remove(pid); | |
boliu
2017/04/20 22:33:34
\o/
Jay Civelli
2017/04/25 06:02:46
Acknowledged.
| |
454 managedConnection.clearConnection(); | |
boliu
2017/04/20 22:33:34
clearConnection can be outside of lock
Jay Civelli
2017/04/25 06:02:46
Done.
| |
455 } | |
464 } | 456 } |
465 return managedConnection != null ? managedConnection.isOomProtected() : false; | |
466 } | |
467 | |
468 @Override | |
469 public void clearConnection(int pid) { | |
470 ManagedConnection managedConnection; | |
471 synchronized (mManagedConnections) { | |
472 managedConnection = mManagedConnections.get(pid); | |
473 } | |
474 if (managedConnection != null) managedConnection.clearConnection(); | |
475 } | 457 } |
476 | 458 |
477 /** @return true iff the connection reference is no longer held */ | 459 /** @return true iff the connection reference is no longer held */ |
478 @VisibleForTesting | 460 @VisibleForTesting |
479 public boolean isConnectionCleared(int pid) { | 461 public boolean isConnectionCleared(int pid) { |
480 synchronized (mManagedConnections) { | 462 synchronized (mManagedConnections) { |
481 return mManagedConnections.get(pid).isConnectionCleared(); | 463 return mManagedConnections.get(pid).isConnectionCleared(); |
482 } | 464 } |
483 } | 465 } |
484 | 466 |
485 @Override | 467 @Override |
486 public void startModerateBindingManagement(Context context, int maxSize) { | 468 public void startModerateBindingManagement(Context context, int maxSize) { |
487 if (mIsLowMemoryDevice) return; | 469 if (mIsLowMemoryDevice) return; |
488 ModerateBindingPool pool = new ModerateBindingPool(maxSize); | 470 ModerateBindingPool pool = new ModerateBindingPool(maxSize); |
489 if (mModerateBindingPool.compareAndSet(null, pool)) { | 471 if (mModerateBindingPool.compareAndSet(null, pool)) { |
490 Log.i(TAG, "Moderate binding enabled: maxSize=%d", maxSize); | 472 Log.i(TAG, "Moderate binding enabled: maxSize=%d", maxSize); |
491 if (context != null) context.registerComponentCallbacks(pool); | 473 if (context != null) context.registerComponentCallbacks(pool); |
492 } | 474 } |
493 } | 475 } |
494 | 476 |
495 @Override | 477 @Override |
496 public void releaseAllModerateBindings() { | 478 public void releaseAllModerateBindings() { |
497 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); | 479 ModerateBindingPool moderateBindingPool = mModerateBindingPool.get(); |
498 if (moderateBindingPool != null) { | 480 if (moderateBindingPool != null) { |
499 Log.i(TAG, "Release all moderate bindings: %d", moderateBindingPool. size()); | 481 Log.i(TAG, "Release all moderate bindings: %d", moderateBindingPool. size()); |
500 moderateBindingPool.evictAll(); | 482 moderateBindingPool.evictAll(); |
501 } | 483 } |
502 } | 484 } |
503 } | 485 } |
OLD | NEW |