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.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 |