Chromium Code Reviews| 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.util.Log; | 7 import android.annotation.TargetApi; |
| 8 import android.content.ComponentCallbacks2; | |
| 9 import android.content.Context; | |
| 10 import android.content.res.Configuration; | |
| 11 import android.os.Build; | |
| 12 import android.util.LruCache; | |
| 8 import android.util.SparseArray; | 13 import android.util.SparseArray; |
| 9 | 14 |
| 15 import org.chromium.base.Log; | |
| 10 import org.chromium.base.SysUtils; | 16 import org.chromium.base.SysUtils; |
| 11 import org.chromium.base.ThreadUtils; | 17 import org.chromium.base.ThreadUtils; |
| 12 import org.chromium.base.VisibleForTesting; | 18 import org.chromium.base.VisibleForTesting; |
| 19 import org.chromium.base.metrics.RecordHistogram; | |
| 20 | |
| 21 import java.util.Map; | |
| 13 | 22 |
| 14 /** | 23 /** |
| 15 * Manages oom bindings used to bound child services. | 24 * Manages oom bindings used to bound child services. |
| 16 */ | 25 */ |
| 17 class BindingManagerImpl implements BindingManager { | 26 class BindingManagerImpl implements BindingManager { |
| 18 private static final String TAG = "BindingManager"; | 27 private static final String TAG = "cr.BindingManager"; |
| 19 | 28 |
| 20 // Delay of 1 second used when removing temporary strong binding of a proces s (only on | 29 // Delay of 1 second used when removing temporary strong binding of a proces s (only on |
| 21 // non-low-memory devices). | 30 // non-low-memory devices). |
| 22 private static final long DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS = 1 * 1000; | 31 private static final long DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS = 1 * 1000; |
| 23 | 32 |
| 24 // These fields allow to override the parameters for testing - see | 33 // These fields allow to override the parameters for testing - see |
| 25 // createBindingManagerForTesting(). | 34 // createBindingManagerForTesting(). |
| 26 private final long mRemoveStrongBindingDelay; | 35 private final long mRemoveStrongBindingDelay; |
| 27 private final boolean mIsLowMemoryDevice; | 36 private final boolean mIsLowMemoryDevice; |
| 28 | 37 |
| 38 private static class ModerateBindingPool | |
| 39 extends LruCache<Integer, ManagedConnection> implements ComponentCal lbacks2 { | |
| 40 private final float mLowReduceRatio; | |
| 41 private final float mHighReduceRatio; | |
| 42 | |
| 43 public ModerateBindingPool(int maxSize, float lowReduceRatio, float high ReduceRatio) { | |
| 44 super(maxSize); | |
| 45 | |
| 46 mLowReduceRatio = lowReduceRatio; | |
| 47 mHighReduceRatio = highReduceRatio; | |
| 48 } | |
| 49 | |
| 50 @Override | |
| 51 public void onTrimMemory(int level) { | |
| 52 Log.i(TAG, "onTrimMemory: level=" + level + ", size=" + size()); | |
| 53 if (size() > 0) { | |
| 54 if (level <= TRIM_MEMORY_RUNNING_MODERATE) { | |
| 55 reduce(mLowReduceRatio); | |
| 56 } else if (level <= TRIM_MEMORY_RUNNING_LOW) { | |
| 57 reduce(mHighReduceRatio); | |
| 58 } else { | |
| 59 evictAll(); | |
| 60 } | |
| 61 } | |
| 62 } | |
| 63 | |
| 64 @Override | |
| 65 public void onLowMemory() { | |
| 66 Log.i(TAG, "onLowMemory: evict " + size() + " bindings"); | |
| 67 evictAll(); | |
| 68 } | |
| 69 | |
| 70 @Override | |
| 71 public void onConfigurationChanged(Configuration configuration) {} | |
| 72 | |
| 73 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) | |
| 74 private void reduce(float reduceRatio) { | |
| 75 int oldSize = size(); | |
| 76 int newSize = (int) (oldSize * (1f - reduceRatio)); | |
| 77 Log.i(TAG, "Reduce connections from " + oldSize + " to " + newSize); | |
| 78 if (newSize == 0) { | |
| 79 evictAll(); | |
| 80 } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_M R1) { | |
| 81 trimToSize(newSize); | |
| 82 } else { | |
|
Jaekyun Seok (inactive)
2015/06/22 03:17:52
I realized that LruCache.trimToSize is available o
| |
| 83 int count = 0; | |
| 84 for (Map.Entry<Integer, ManagedConnection> entry : snapshot().en trySet()) { | |
|
Alexei Svitkine (slow)
2015/06/22 14:58:52
Nit: Add a comment explaining why this makes sense
Jaekyun Seok (inactive)
2015/06/22 21:24:48
Done.
| |
| 85 remove(entry.getKey()); | |
| 86 ++count; | |
| 87 if (count == oldSize - newSize) break; | |
| 88 } | |
| 89 } | |
| 90 } | |
| 91 | |
| 92 void addConnection(ManagedConnection managedConnection) { | |
| 93 ChildProcessConnection connection = managedConnection.mConnection; | |
| 94 if (connection != null && connection.isInSandbox()) { | |
| 95 managedConnection.addModerateBinding(); | |
| 96 if (connection.isModerateBindingBound()) { | |
| 97 put(connection.getServiceNumber(), managedConnection); | |
| 98 } else { | |
| 99 remove(connection.getServiceNumber()); | |
| 100 } | |
| 101 } | |
| 102 } | |
| 103 | |
| 104 void removeConnection(ManagedConnection managedConnection) { | |
| 105 ChildProcessConnection connection = managedConnection.mConnection; | |
| 106 if (connection != null && connection.isInSandbox()) { | |
| 107 remove(connection.getServiceNumber()); | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 @Override | |
| 112 protected void entryRemoved(boolean evicted, Integer key, ManagedConnect ion oldValue, | |
| 113 ManagedConnection newValue) { | |
| 114 if (oldValue != newValue) { | |
| 115 oldValue.removeModerateBinding(); | |
| 116 } | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 private ModerateBindingPool mModerateBindingPool; | |
| 121 | |
| 29 /** | 122 /** |
| 30 * Wraps ChildProcessConnection keeping track of additional information need ed to manage the | 123 * Wraps ChildProcessConnection keeping track of additional information need ed to manage the |
| 31 * bindings of the connection. The reference to ChildProcessConnection is cl eared when the | 124 * bindings of the connection. The reference to ChildProcessConnection is cl eared when the |
| 32 * connection goes away, but ManagedConnection itself is kept (until overwri tten by a new entry | 125 * connection goes away, but ManagedConnection itself is kept (until overwri tten by a new entry |
| 33 * for the same pid). | 126 * for the same pid). |
| 34 */ | 127 */ |
| 35 private class ManagedConnection { | 128 private class ManagedConnection { |
| 36 // Set in constructor, cleared in clearConnection(). | 129 // Set in constructor, cleared in clearConnection(). |
| 37 private ChildProcessConnection mConnection; | 130 private ChildProcessConnection mConnection; |
| 38 | 131 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 52 if (mConnection == null || !mConnection.isInitialBindingBound()) ret urn; | 145 if (mConnection == null || !mConnection.isInitialBindingBound()) ret urn; |
| 53 mConnection.removeInitialBinding(); | 146 mConnection.removeInitialBinding(); |
| 54 } | 147 } |
| 55 | 148 |
| 56 /** Adds a strong service binding. */ | 149 /** Adds a strong service binding. */ |
| 57 private void addStrongBinding() { | 150 private void addStrongBinding() { |
| 58 ChildProcessConnection connection = mConnection; | 151 ChildProcessConnection connection = mConnection; |
| 59 if (connection == null) return; | 152 if (connection == null) return; |
| 60 | 153 |
| 61 connection.addStrongBinding(); | 154 connection.addStrongBinding(); |
| 155 if (mModerateBindingPool != null) { | |
| 156 mModerateBindingPool.removeConnection(this); | |
| 157 } | |
| 62 } | 158 } |
| 63 | 159 |
| 64 /** Removes a strong service binding. */ | 160 /** Removes a strong service binding. */ |
| 65 private void removeStrongBinding() { | 161 private void removeStrongBinding(final boolean keepsAsModerate) { |
| 66 final ChildProcessConnection connection = mConnection; | 162 final ChildProcessConnection connection = mConnection; |
| 67 // We have to fail gracefully if the strong binding is not present, as on low-end the | 163 // We have to fail gracefully if the strong binding is not present, as on low-end the |
| 68 // binding could have been removed by dropOomBindings() when a new s ervice was started. | 164 // binding could have been removed by dropOomBindings() when a new s ervice was started. |
| 69 if (connection == null || !connection.isStrongBindingBound()) return ; | 165 if (connection == null || !connection.isStrongBindingBound()) return ; |
| 70 | 166 |
| 71 // This runnable performs the actual unbinding. It will be executed synchronously when | 167 // This runnable performs the actual unbinding. It will be executed synchronously when |
| 72 // on low-end devices and posted with a delay otherwise. | 168 // on low-end devices and posted with a delay otherwise. |
| 73 Runnable doUnbind = new Runnable() { | 169 Runnable doUnbind = new Runnable() { |
| 74 @Override | 170 @Override |
| 75 public void run() { | 171 public void run() { |
| 76 if (connection.isStrongBindingBound()) { | 172 if (connection.isStrongBindingBound()) { |
| 77 connection.removeStrongBinding(); | 173 connection.removeStrongBinding(); |
| 174 if (mModerateBindingPool != null && !connection.isStrong BindingBound() | |
| 175 && keepsAsModerate) { | |
| 176 mModerateBindingPool.addConnection(ManagedConnection .this); | |
| 177 } | |
| 78 } | 178 } |
| 79 } | 179 } |
| 80 }; | 180 }; |
| 81 | 181 |
| 82 if (mIsLowMemoryDevice) { | 182 if (mIsLowMemoryDevice) { |
| 83 doUnbind.run(); | 183 doUnbind.run(); |
| 84 } else { | 184 } else { |
| 85 ThreadUtils.postOnUiThreadDelayed(doUnbind, mRemoveStrongBinding Delay); | 185 ThreadUtils.postOnUiThreadDelayed(doUnbind, mRemoveStrongBinding Delay); |
| 86 } | 186 } |
| 87 } | 187 } |
| 88 | 188 |
| 189 /** Removes the moderate service binding. */ | |
| 190 private void removeModerateBinding() { | |
| 191 if (mConnection == null || !mConnection.isModerateBindingBound()) re turn; | |
| 192 mConnection.removeModerateBinding(); | |
| 193 } | |
| 194 | |
| 195 /** Adds the moderate service binding. */ | |
| 196 private void addModerateBinding() { | |
| 197 ChildProcessConnection connection = mConnection; | |
| 198 if (connection == null) return; | |
| 199 | |
| 200 connection.addModerateBinding(); | |
| 201 } | |
| 202 | |
| 89 /** | 203 /** |
| 90 * Drops the service bindings. This is used on low-end to drop bindings of the current | 204 * Drops the service bindings. This is used on low-end to drop bindings of the current |
| 91 * service when a new one is used in foreground. | 205 * service when a new one is used in foreground. |
| 92 */ | 206 */ |
| 93 private void dropBindings() { | 207 private void dropBindings() { |
| 94 assert mIsLowMemoryDevice; | 208 assert mIsLowMemoryDevice; |
| 95 ChildProcessConnection connection = mConnection; | 209 ChildProcessConnection connection = mConnection; |
| 96 if (connection == null) return; | 210 if (connection == null) return; |
| 97 | 211 |
| 98 connection.dropOomBindings(); | 212 connection.dropOomBindings(); |
| 99 } | 213 } |
| 100 | 214 |
| 101 ManagedConnection(ChildProcessConnection connection) { | 215 ManagedConnection(ChildProcessConnection connection) { |
| 102 mConnection = connection; | 216 mConnection = connection; |
| 103 } | 217 } |
| 104 | 218 |
| 105 /** | 219 /** |
| 106 * Sets the visibility of the service, adding or removing the strong bin ding as needed. | 220 * Sets the visibility of the service, adding or removing the strong bin ding as needed. |
| 107 */ | 221 */ |
| 108 void setInForeground(boolean nextInForeground) { | 222 void setInForeground(boolean nextInForeground) { |
| 109 if (!mInForeground && nextInForeground) { | 223 if (!mInForeground && nextInForeground) { |
| 110 addStrongBinding(); | 224 addStrongBinding(); |
| 111 } else if (mInForeground && !nextInForeground) { | 225 } else if (mInForeground && !nextInForeground) { |
| 112 removeStrongBinding(); | 226 removeStrongBinding(true); |
| 113 } | 227 } |
| 114 | 228 |
| 115 mInForeground = nextInForeground; | 229 mInForeground = nextInForeground; |
| 116 } | 230 } |
| 117 | 231 |
| 118 /** | 232 /** |
| 119 * Removes the initial binding. | 233 * Removes the initial binding. |
| 120 */ | 234 */ |
| 121 void determinedVisibility() { | 235 void determinedVisibility() { |
| 122 removeInitialBinding(); | 236 removeInitialBinding(); |
| 123 } | 237 } |
| 124 | 238 |
| 125 /** | 239 /** |
| 126 * Sets or removes additional binding when the service is main service d uring the embedder | 240 * Sets or removes additional binding when the service is main service d uring the embedder |
| 127 * background period. | 241 * background period. |
| 128 */ | 242 */ |
| 129 void setBoundForBackgroundPeriod(boolean nextBound) { | 243 void setBoundForBackgroundPeriod(boolean nextBound) { |
| 130 if (!mBoundForBackgroundPeriod && nextBound) { | 244 if (!mBoundForBackgroundPeriod && nextBound) { |
| 131 addStrongBinding(); | 245 addStrongBinding(); |
| 132 } else if (mBoundForBackgroundPeriod && !nextBound) { | 246 } else if (mBoundForBackgroundPeriod && !nextBound) { |
| 133 removeStrongBinding(); | 247 removeStrongBinding(false); |
| 134 } | 248 } |
| 135 | 249 |
| 136 mBoundForBackgroundPeriod = nextBound; | 250 mBoundForBackgroundPeriod = nextBound; |
| 137 } | 251 } |
| 138 | 252 |
| 139 boolean isOomProtected() { | 253 boolean isOomProtected() { |
| 140 // When a process crashes, we can be queried about its oom status be fore or after the | 254 // When a process crashes, we can be queried about its oom status be fore or after the |
| 141 // connection is cleared. For the latter case, the oom status is sta shed in | 255 // connection is cleared. For the latter case, the oom status is sta shed in |
| 142 // mWasOomProtected. | 256 // mWasOomProtected. |
| 143 return mConnection != null | 257 return mConnection != null |
| 144 ? mConnection.isOomProtectedOrWasWhenDied() : mWasOomProtect ed; | 258 ? mConnection.isOomProtectedOrWasWhenDied() : mWasOomProtect ed; |
| 145 } | 259 } |
| 146 | 260 |
| 147 void clearConnection() { | 261 void clearConnection() { |
| 148 mWasOomProtected = mConnection.isOomProtectedOrWasWhenDied(); | 262 mWasOomProtected = mConnection.isOomProtectedOrWasWhenDied(); |
| 263 if (mModerateBindingPool != null) { | |
| 264 mModerateBindingPool.removeConnection(this); | |
| 265 } | |
| 149 mConnection = null; | 266 mConnection = null; |
| 150 } | 267 } |
| 151 | 268 |
| 152 /** @return true iff the reference to the connection is no longer held * / | 269 /** @return true iff the reference to the connection is no longer held * / |
| 153 @VisibleForTesting | 270 @VisibleForTesting |
| 154 boolean isConnectionCleared() { | 271 boolean isConnectionCleared() { |
| 155 return mConnection == null; | 272 return mConnection == null; |
| 156 } | 273 } |
| 157 } | 274 } |
| 158 | 275 |
| 159 // This can be manipulated on different threads, synchronize access on mMana gedConnections. | 276 // This can be manipulated on different threads, synchronize access on mMana gedConnections. |
| 160 private final SparseArray<ManagedConnection> mManagedConnections = | 277 private final SparseArray<ManagedConnection> mManagedConnections = |
| 161 new SparseArray<ManagedConnection>(); | 278 new SparseArray<ManagedConnection>(); |
| 162 | 279 |
| 163 // The connection that was most recently set as foreground (using setInForeg round()). This is | 280 // The connection that was most recently set as foreground (using setInForeg round()). This is |
| 164 // used to add additional binding on it when the embedder goes to background . On low-end, this | 281 // used to add additional binding on it when the embedder goes to background . On low-end, this |
| 165 // is also used to drop process bidnings when a new one is created, making s ure that only one | 282 // is also used to drop process bidnings when a new one is created, making s ure that only one |
| 166 // renderer process at a time is protected from oom killing. | 283 // renderer process at a time is protected from oom killing. |
| 167 private ManagedConnection mLastInForeground; | 284 private ManagedConnection mLastInForeground; |
| 168 | 285 |
| 169 // Synchronizes operations that access mLastInForeground: setInForeground() and | 286 // Synchronizes operations that access mLastInForeground: setInForeground() and |
| 170 // addNewConnection(). | 287 // addNewConnection(). |
| 171 private final Object mLastInForegroundLock = new Object(); | 288 private final Object mLastInForegroundLock = new Object(); |
| 172 | 289 |
| 173 // The connection bound with additional binding in onSentToBackground(). | 290 // The connection bound with additional binding in onSentToBackground(). |
| 174 private ManagedConnection mBoundForBackgroundPeriod; | 291 private ManagedConnection mBoundForBackgroundPeriod; |
| 175 | 292 |
| 293 // Whether this instance is used on testing. | |
| 294 private final boolean mOnTesting; | |
| 295 | |
| 176 /** | 296 /** |
| 177 * The constructor is private to hide parameters exposed for testing from th e regular consumer. | 297 * The constructor is private to hide parameters exposed for testing from th e regular consumer. |
| 178 * Use factory methods to create an instance. | 298 * Use factory methods to create an instance. |
| 179 */ | 299 */ |
| 180 private BindingManagerImpl(boolean isLowMemoryDevice, long removeStrongBindi ngDelay) { | 300 private BindingManagerImpl( |
| 301 boolean isLowMemoryDevice, long removeStrongBindingDelay, boolean on Testing) { | |
| 181 mIsLowMemoryDevice = isLowMemoryDevice; | 302 mIsLowMemoryDevice = isLowMemoryDevice; |
| 182 mRemoveStrongBindingDelay = removeStrongBindingDelay; | 303 mRemoveStrongBindingDelay = removeStrongBindingDelay; |
| 304 mOnTesting = onTesting; | |
| 183 } | 305 } |
| 184 | 306 |
| 185 public static BindingManagerImpl createBindingManager() { | 307 public static BindingManagerImpl createBindingManager() { |
| 186 return new BindingManagerImpl(SysUtils.isLowEndDevice(), | 308 return new BindingManagerImpl( |
| 187 DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS); | 309 SysUtils.isLowEndDevice(), DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLI S, false); |
| 188 } | 310 } |
| 189 | 311 |
| 190 /** | 312 /** |
| 191 * Creates a testing instance of BindingManager. Testing instance will have the unbinding delays | 313 * Creates a testing instance of BindingManager. Testing instance will have the unbinding delays |
| 192 * set to 0, so that the tests don't need to deal with actual waiting. | 314 * set to 0, so that the tests don't need to deal with actual waiting. |
| 193 * @param isLowEndDevice true iff the created instance should apply low-end binding policies | 315 * @param isLowEndDevice true iff the created instance should apply low-end binding policies |
| 194 */ | 316 */ |
| 195 public static BindingManagerImpl createBindingManagerForTesting(boolean isLo wEndDevice) { | 317 public static BindingManagerImpl createBindingManagerForTesting(boolean isLo wEndDevice) { |
| 196 return new BindingManagerImpl(isLowEndDevice, 0); | 318 return new BindingManagerImpl(isLowEndDevice, 0, true); |
| 197 } | 319 } |
| 198 | 320 |
| 199 @Override | 321 @Override |
| 200 public void addNewConnection(int pid, ChildProcessConnection connection) { | 322 public void addNewConnection(int pid, ChildProcessConnection connection) { |
| 201 // This will reset the previous entry for the pid in the unlikely event of the OS | 323 // This will reset the previous entry for the pid in the unlikely event of the OS |
| 202 // reusing renderer pids. | 324 // reusing renderer pids. |
| 203 synchronized (mManagedConnections) { | 325 synchronized (mManagedConnections) { |
| 204 mManagedConnections.put(pid, new ManagedConnection(connection)); | 326 mManagedConnections.put(pid, new ManagedConnection(connection)); |
| 205 } | 327 } |
| 206 } | 328 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 public void onSentToBackground() { | 371 public void onSentToBackground() { |
| 250 assert mBoundForBackgroundPeriod == null; | 372 assert mBoundForBackgroundPeriod == null; |
| 251 synchronized (mLastInForegroundLock) { | 373 synchronized (mLastInForegroundLock) { |
| 252 // mLastInForeground can be null at this point as the embedding appl ication could be | 374 // mLastInForeground can be null at this point as the embedding appl ication could be |
| 253 // used in foreground without spawning any renderers. | 375 // used in foreground without spawning any renderers. |
| 254 if (mLastInForeground != null) { | 376 if (mLastInForeground != null) { |
| 255 mLastInForeground.setBoundForBackgroundPeriod(true); | 377 mLastInForeground.setBoundForBackgroundPeriod(true); |
| 256 mBoundForBackgroundPeriod = mLastInForeground; | 378 mBoundForBackgroundPeriod = mLastInForeground; |
| 257 } | 379 } |
| 258 } | 380 } |
| 381 if (mModerateBindingPool != null) { | |
| 382 Log.i(TAG, "Release moderate connections: " + mModerateBindingPool.s ize()); | |
| 383 if (!mOnTesting) { | |
| 384 RecordHistogram.recordCountHistogram( | |
| 385 "Android.ModerateBindingCount", mModerateBindingPool.siz e()); | |
| 386 } | |
| 387 mModerateBindingPool.evictAll(); | |
| 388 } | |
| 259 } | 389 } |
| 260 | 390 |
| 261 @Override | 391 @Override |
| 262 public void onBroughtToForeground() { | 392 public void onBroughtToForeground() { |
| 263 if (mBoundForBackgroundPeriod != null) { | 393 if (mBoundForBackgroundPeriod != null) { |
| 264 mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false); | 394 mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false); |
| 265 mBoundForBackgroundPeriod = null; | 395 mBoundForBackgroundPeriod = null; |
| 266 } | 396 } |
| 267 } | 397 } |
| 268 | 398 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 287 if (managedConnection != null) managedConnection.clearConnection(); | 417 if (managedConnection != null) managedConnection.clearConnection(); |
| 288 } | 418 } |
| 289 | 419 |
| 290 /** @return true iff the connection reference is no longer held */ | 420 /** @return true iff the connection reference is no longer held */ |
| 291 @VisibleForTesting | 421 @VisibleForTesting |
| 292 public boolean isConnectionCleared(int pid) { | 422 public boolean isConnectionCleared(int pid) { |
| 293 synchronized (mManagedConnections) { | 423 synchronized (mManagedConnections) { |
| 294 return mManagedConnections.get(pid).isConnectionCleared(); | 424 return mManagedConnections.get(pid).isConnectionCleared(); |
| 295 } | 425 } |
| 296 } | 426 } |
| 427 | |
| 428 @Override | |
| 429 public void startModerateBindingManagement( | |
| 430 Context context, int maxSize, float lowReduceRatio, float highReduce Ratio) { | |
| 431 if (mIsLowMemoryDevice || mModerateBindingPool != null) return; | |
| 432 | |
| 433 Log.i(TAG, "Moderate binding enabled: maxSize=" + maxSize + " lowReduceR atio=" | |
| 434 + lowReduceRatio + " highReduceRatio=" + highReduceRatio ); | |
| 435 mModerateBindingPool = new ModerateBindingPool(maxSize, lowReduceRatio, highReduceRatio); | |
| 436 if (context != null) context.registerComponentCallbacks(mModerateBinding Pool); | |
| 437 } | |
| 297 } | 438 } |
| OLD | NEW |