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

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

Issue 1307793003: Execute operations of ChildProcessLauncher on launcher thread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix PrerenderServiceTest and ChildProcessLauncherTest Created 5 years, 4 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 2eaf20eb1a23a47564349189b4176f946254269f..aa4770d06516a41a52282b263404f3799d40405b 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
@@ -35,47 +35,68 @@ class BindingManagerImpl implements BindingManager {
private static final long MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS = 10 * 1000;
private static final long MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS_ON_TESTING = 100;
+ // ManagedConnection is accessed even after it is cleared because whether it was OOM protected
+ // or not is queried later. So we need to keep it in memory for a while.
+ private static final long MANAGED_CONNECTION_DELETE_DELAY_MILLS = 3 * 1000;
+
// These fields allow to override the parameters for testing - see
// createBindingManagerForTesting().
private final long mRemoveStrongBindingDelay;
private final boolean mIsLowMemoryDevice;
+ interface LauncherThreadExecutor {
Yaron 2015/09/04 16:04:04 This is basically a static but you're wrapping to
Jaekyun Seok (inactive) 2015/09/08 09:45:12 This is only for BindingManagerImplTest which is a
+ void execute(Runnable runnable);
+ }
+
private static class ModerateBindingPool
extends LruCache<Integer, ManagedConnection> implements ComponentCallbacks2 {
private final float mLowReduceRatio;
private final float mHighReduceRatio;
+ private final LauncherThreadExecutor mLauncherThreadExecutor;
private final Object mDelayedClearerLock = new Object();
private Runnable mDelayedClearer;
private final Handler mHandler = new Handler(ThreadUtils.getUiThreadLooper());
- public ModerateBindingPool(int maxSize, float lowReduceRatio, float highReduceRatio) {
+ public ModerateBindingPool(int maxSize, float lowReduceRatio, float highReduceRatio,
+ LauncherThreadExecutor executor) {
super(maxSize);
mLowReduceRatio = lowReduceRatio;
mHighReduceRatio = highReduceRatio;
+ mLauncherThreadExecutor = executor;
}
@Override
- public void onTrimMemory(int level) {
- Log.i(TAG, "onTrimMemory: level=%d, size=%d", level, size());
- if (size() > 0) {
- if (level <= TRIM_MEMORY_RUNNING_MODERATE) {
- reduce(mLowReduceRatio);
- } else if (level <= TRIM_MEMORY_RUNNING_LOW) {
- reduce(mHighReduceRatio);
- } else if (level == TRIM_MEMORY_UI_HIDDEN) {
- // This will be handled by |mDelayedClearer|.
- return;
- } else {
- evictAll();
+ public void onTrimMemory(final int level) {
+ mLauncherThreadExecutor.execute(new Runnable() {
+ @Override
Yaron 2015/09/04 16:04:04 Here you're posting to launcher thread within the
Jaekyun Seok (inactive) 2015/09/08 09:45:12 I separated ComponentCallbacks2 from ModerateBindi
Yaron 2015/09/09 01:00:20 Nice, this helps
+ public void run() {
+ Log.i(TAG, "onTrimMemory: level=%d, size=%d", level, size());
+ if (size() > 0) {
+ if (level <= TRIM_MEMORY_RUNNING_MODERATE) {
+ reduce(mLowReduceRatio);
+ } else if (level <= TRIM_MEMORY_RUNNING_LOW) {
+ reduce(mHighReduceRatio);
+ } else if (level == TRIM_MEMORY_UI_HIDDEN) {
+ // This will be handled by |mDelayedClearer|.
+ return;
+ } else {
+ evictAll();
+ }
+ }
}
- }
+ });
}
@Override
public void onLowMemory() {
- Log.i(TAG, "onLowMemory: evict %d bindings", size());
- evictAll();
+ mLauncherThreadExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ Log.i(TAG, "onLowMemory: evict %d bindings", size());
+ evictAll();
+ }
+ });
}
@Override
@@ -139,12 +160,17 @@ class BindingManagerImpl implements BindingManager {
if (mDelayedClearer == null) return;
mDelayedClearer = null;
}
- Log.i(TAG, "Release moderate connections: %d", size());
- if (!onTesting) {
- RecordHistogram.recordCountHistogram(
- "Android.ModerateBindingCount", size());
- }
- evictAll();
+ mLauncherThreadExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ Log.i(TAG, "Release moderate connections: %d", size());
+ if (!onTesting) {
+ RecordHistogram.recordCountHistogram(
+ "Android.ModerateBindingCount", size());
+ }
+ evictAll();
+ }
+ });
}
};
mHandler.postDelayed(mDelayedClearer, onTesting
Yaron 2015/09/04 16:04:04 This function is now very peculiar. We have an mHa
Jaekyun Seok (inactive) 2015/09/08 09:45:11 I will add a native wrapper for posting, but in th
@@ -214,7 +240,7 @@ class BindingManagerImpl implements BindingManager {
// This runnable performs the actual unbinding. It will be executed synchronously when
// on low-end devices and posted with a delay otherwise.
- Runnable doUnbind = new Runnable() {
+ final Runnable doUnbind = new Runnable() {
@Override
public void run() {
if (connection.isStrongBindingBound()) {
@@ -234,7 +260,12 @@ class BindingManagerImpl implements BindingManager {
if (mIsLowMemoryDevice) {
doUnbind.run();
} else {
- ThreadUtils.postOnUiThreadDelayed(doUnbind, mRemoveStrongBindingDelay);
+ ThreadUtils.postOnUiThreadDelayed(new Runnable() {
Yaron 2015/09/04 16:04:03 General question: it seems like in many places we
Jaekyun Seok (inactive) 2015/09/08 09:45:11 Added a native wrapper to post a task on launcher
+ @Override
+ public void run() {
+ mLauncherThreadExecutor.execute(doUnbind);
+ }
+ }, mRemoveStrongBindingDelay);
}
}
@@ -347,20 +378,24 @@ class BindingManagerImpl implements BindingManager {
// Whether this instance is used on testing.
private final boolean mOnTesting;
+ // Executor that executes a task on LauncherThread.
+ private final LauncherThreadExecutor mLauncherThreadExecutor;
+
/**
* 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, boolean onTesting) {
+ private BindingManagerImpl(boolean isLowMemoryDevice, long removeStrongBindingDelay,
+ boolean onTesting, LauncherThreadExecutor executor) {
mIsLowMemoryDevice = isLowMemoryDevice;
mRemoveStrongBindingDelay = removeStrongBindingDelay;
mOnTesting = onTesting;
+ mLauncherThreadExecutor = executor;
}
- public static BindingManagerImpl createBindingManager() {
+ public static BindingManagerImpl createBindingManager(LauncherThreadExecutor executor) {
return new BindingManagerImpl(
- SysUtils.isLowEndDevice(), DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS, false);
+ SysUtils.isLowEndDevice(), DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS, false, executor);
}
/**
@@ -369,7 +404,13 @@ 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, true);
+ LauncherThreadExecutor executor = new LauncherThreadExecutor() {
+ @Override
+ public void execute(Runnable runnable) {
+ runnable.run();
+ }
+ };
+ return new BindingManagerImpl(isLowEndDevice, 0, true, executor);
}
@Override
@@ -464,19 +505,36 @@ class BindingManagerImpl implements BindingManager {
}
@Override
- public void clearConnection(int pid) {
+ public void clearConnection(final int pid) {
ManagedConnection managedConnection;
synchronized (mManagedConnections) {
managedConnection = mManagedConnections.get(pid);
}
- if (managedConnection != null) managedConnection.clearConnection();
+ if (managedConnection != null) {
+ managedConnection.clearConnection();
+ final Runnable cleaner = new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mManagedConnections) {
+ mManagedConnections.delete(pid);
+ }
+ }
+ };
+ ThreadUtils.postOnUiThreadDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mLauncherThreadExecutor.execute(cleaner);
+ }
+ }, MANAGED_CONNECTION_DELETE_DELAY_MILLS);
Yaron 2015/09/04 16:04:04 This was intentionally leaky (specifically for the
Jaekyun Seok (inactive) 2015/09/08 09:45:12 I picked 3s because I thought that it was big enou
Yaron 2015/09/09 01:00:20 I think that's the only reason. Still, I think we
+ }
}
/** @return true iff the connection reference is no longer held */
@VisibleForTesting
public boolean isConnectionCleared(int pid) {
synchronized (mManagedConnections) {
- return mManagedConnections.get(pid).isConnectionCleared();
+ ManagedConnection managedConnection = mManagedConnections.get(pid);
+ return managedConnection == null || managedConnection.isConnectionCleared();
}
}
@@ -488,8 +546,8 @@ class BindingManagerImpl implements BindingManager {
Log.i(TAG, "Moderate binding enabled: maxSize=%d lowReduceRatio=%f highReduceRatio=%f",
maxSize, lowReduceRatio, highReduceRatio);
- mModerateBindingPool =
- new ModerateBindingPool(maxSize, lowReduceRatio, highReduceRatio);
+ mModerateBindingPool = new ModerateBindingPool(
+ maxSize, lowReduceRatio, highReduceRatio, mLauncherThreadExecutor);
if (context != null) context.registerComponentCallbacks(mModerateBindingPool);
}
}

Powered by Google App Engine
This is Rietveld 408576698