Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java

Issue 1146813010: Introduce moderate binding (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java b/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java
index 728699e38e7192555aeca66f39eaa39dfa456517..e78f02b055859c2673e1b0463b87167fbe944a81 100644
--- a/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/BindingManagerImpl.java
@@ -4,18 +4,23 @@
package org.chromium.content.browser;
-import android.util.Log;
+import android.content.ComponentCallbacks2;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.util.LruCache;
import android.util.SparseArray;
+import org.chromium.base.Log;
import org.chromium.base.SysUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
+import org.chromium.base.metrics.RecordHistogram;
/**
* Manages oom bindings used to bound child services.
*/
class BindingManagerImpl implements BindingManager {
- private static final String TAG = "BindingManager";
+ private static final String TAG = "cr.BindingManager";
// Delay of 1 second used when removing temporary strong binding of a process (only on
// non-low-memory devices).
@@ -26,6 +31,81 @@ class BindingManagerImpl implements BindingManager {
private final long mRemoveStrongBindingDelay;
private final boolean mIsLowMemoryDevice;
+ private static class ModerateBindingPool
+ extends LruCache<Integer, ManagedConnection> implements ComponentCallbacks2 {
+ private final float mLowReduceRatio;
+ private final float mHighReduceRatio;
+
+ public ModerateBindingPool(int maxSize, float lowReduceRatio, float highReduceRatio) {
+ super(maxSize);
+
+ mLowReduceRatio = lowReduceRatio;
+ mHighReduceRatio = highReduceRatio;
+ }
+
+ @Override
+ public void onTrimMemory(int level) {
+ Log.i(TAG, "onTrimMemory: level=" + level + ", size=" + size());
+ if (size() > 0) {
+ if (level <= TRIM_MEMORY_RUNNING_MODERATE) {
+ reduce(mLowReduceRatio);
+ } else if (level <= TRIM_MEMORY_RUNNING_LOW) {
+ reduce(mHighReduceRatio);
+ } else {
+ evictAll();
+ }
+ }
+ }
+
+ @Override
+ public void onLowMemory() {
+ Log.i(TAG, "onLowMemory: evict " + size() + " bindings");
+ evictAll();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration configuration) {}
+
+ private void reduce(float reduceRatio) {
+ int newSize = (int) (size() * (1f - reduceRatio));
+ Log.i(TAG, "Reduce connections from " + size() + " to " + newSize);
+ if (newSize == 0) {
+ evictAll();
+ } else {
+ trimToSize(newSize);
+ }
+ }
+
+ void addConnection(ManagedConnection managedConnection) {
+ ChildProcessConnection connection = managedConnection.mConnection;
+ if (connection != null && connection.isInSandbox()) {
+ managedConnection.addModerateBinding();
+ if (connection.isModerateBindingBound()) {
+ put(connection.getServiceNumber(), managedConnection);
+ } else {
+ remove(connection.getServiceNumber());
+ }
+ }
+ }
+
+ void removeConnection(ManagedConnection managedConnection) {
+ ChildProcessConnection connection = managedConnection.mConnection;
+ if (connection != null && connection.isInSandbox()) {
+ remove(connection.getServiceNumber());
+ }
+ }
+
+ @Override
+ protected void entryRemoved(boolean evicted, Integer key, ManagedConnection oldValue,
+ ManagedConnection newValue) {
+ if (oldValue != newValue) {
+ oldValue.removeModerateBinding();
+ }
+ }
+ }
+
+ private ModerateBindingPool mModerateBindingPool;
+
/**
* Wraps ChildProcessConnection keeping track of additional information needed to manage the
* bindings of the connection. The reference to ChildProcessConnection is cleared when the
@@ -59,10 +139,13 @@ class BindingManagerImpl implements BindingManager {
if (connection == null) return;
connection.addStrongBinding();
+ if (mModerateBindingPool != null) {
+ mModerateBindingPool.removeConnection(this);
+ }
}
/** Removes a strong service binding. */
- private void removeStrongBinding() {
+ private void removeStrongBinding(final boolean keepsAsModerate) {
final ChildProcessConnection connection = mConnection;
// We have to fail gracefully if the strong binding is not present, as on low-end the
// binding could have been removed by dropOomBindings() when a new service was started.
@@ -75,6 +158,10 @@ class BindingManagerImpl implements BindingManager {
public void run() {
if (connection.isStrongBindingBound()) {
connection.removeStrongBinding();
+ if (mModerateBindingPool != null && !connection.isStrongBindingBound()
+ && keepsAsModerate) {
+ mModerateBindingPool.addConnection(ManagedConnection.this);
+ }
}
}
};
@@ -86,6 +173,20 @@ class BindingManagerImpl implements BindingManager {
}
}
+ /** Removes the moderate service binding. */
+ private void removeModerateBinding() {
+ if (mConnection == null || !mConnection.isModerateBindingBound()) return;
+ mConnection.removeModerateBinding();
+ }
+
+ /** Adds the moderate service binding. */
+ private void addModerateBinding() {
+ ChildProcessConnection connection = mConnection;
+ if (connection == null) return;
+
+ connection.addModerateBinding();
+ }
+
/**
* Drops the service bindings. This is used on low-end to drop bindings of the current
* service when a new one is used in foreground.
@@ -109,7 +210,7 @@ class BindingManagerImpl implements BindingManager {
if (!mInForeground && nextInForeground) {
addStrongBinding();
} else if (mInForeground && !nextInForeground) {
- removeStrongBinding();
+ removeStrongBinding(true);
}
mInForeground = nextInForeground;
@@ -130,7 +231,7 @@ class BindingManagerImpl implements BindingManager {
if (!mBoundForBackgroundPeriod && nextBound) {
addStrongBinding();
} else if (mBoundForBackgroundPeriod && !nextBound) {
- removeStrongBinding();
+ removeStrongBinding(false);
}
mBoundForBackgroundPeriod = nextBound;
@@ -146,6 +247,9 @@ class BindingManagerImpl implements BindingManager {
void clearConnection() {
mWasOomProtected = mConnection.isOomProtectedOrWasWhenDied();
+ if (mModerateBindingPool != null) {
+ mModerateBindingPool.removeConnection(this);
+ }
mConnection = null;
}
@@ -173,18 +277,23 @@ class BindingManagerImpl implements BindingManager {
// The connection bound with additional binding in onSentToBackground().
private ManagedConnection mBoundForBackgroundPeriod;
+ // Whether this instance is used on testing.
+ private boolean mOnTesting;
Yaron 2015/06/17 02:56:12 final
Jaekyun Seok (inactive) 2015/06/17 04:35:46 Done.
+
/**
* The constructor is private to hide parameters exposed for testing from the regular consumer.
* Use factory methods to create an instance.
*/
- private BindingManagerImpl(boolean isLowMemoryDevice, long removeStrongBindingDelay) {
+ private BindingManagerImpl(
+ boolean isLowMemoryDevice, long removeStrongBindingDelay, boolean onTesting) {
mIsLowMemoryDevice = isLowMemoryDevice;
mRemoveStrongBindingDelay = removeStrongBindingDelay;
+ mOnTesting = onTesting;
}
public static BindingManagerImpl createBindingManager() {
- return new BindingManagerImpl(SysUtils.isLowEndDevice(),
- DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS);
+ return new BindingManagerImpl(
+ SysUtils.isLowEndDevice(), DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS, false);
}
/**
@@ -193,7 +302,7 @@ class BindingManagerImpl implements BindingManager {
* @param isLowEndDevice true iff the created instance should apply low-end binding policies
*/
public static BindingManagerImpl createBindingManagerForTesting(boolean isLowEndDevice) {
- return new BindingManagerImpl(isLowEndDevice, 0);
+ return new BindingManagerImpl(isLowEndDevice, 0, true);
}
@Override
@@ -256,6 +365,14 @@ class BindingManagerImpl implements BindingManager {
mBoundForBackgroundPeriod = mLastInForeground;
}
}
+ if (mModerateBindingPool != null) {
+ Log.i(TAG, "Release moderate connections: " + mModerateBindingPool.size());
+ if (!mOnTesting) {
+ RecordHistogram.recordCountHistogram(
+ "Android.ModerateBindingCount", mModerateBindingPool.size());
+ }
+ mModerateBindingPool.evictAll();
+ }
}
@Override
@@ -294,4 +411,15 @@ class BindingManagerImpl implements BindingManager {
return mManagedConnections.get(pid).isConnectionCleared();
}
}
+
+ @Override
+ public void startModerateBindingManagement(
+ Context context, int maxSize, float lowReduceRatio, float highReduceRatio) {
+ if (mIsLowMemoryDevice || mModerateBindingPool != null) return;
+
+ Log.i(TAG, "Moderate binding enabled: maxSize=" + maxSize + " lowReduceRatio="
+ + lowReduceRatio + " highReduceRatio=" + highReduceRatio);
+ mModerateBindingPool = new ModerateBindingPool(maxSize, lowReduceRatio, highReduceRatio);
+ if (context != null) context.registerComponentCallbacks(mModerateBindingPool);
+ }
}

Powered by Google App Engine
This is Rietveld 408576698