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

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: Apply Yaron's comments Created 5 years, 3 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..cda8dce86d962cf9a46dfd4f37c93c90924c3fd6 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
@@ -40,11 +40,18 @@ class BindingManagerImpl implements BindingManager {
private final long mRemoveStrongBindingDelay;
private final boolean mIsLowMemoryDevice;
- private static class ModerateBindingPool
- extends LruCache<Integer, ManagedConnection> implements ComponentCallbacks2 {
+ interface LauncherThreadExecutor {
+ void execute(Runnable runnable);
+ void executeDelayed(Runnable runnable, long delayInMS);
+ }
+
+ /**
+ * Manages moderate bindings. Note that all the public methods should be called from process
+ * launcher thread.
+ */
+ private class ModerateBindingPool extends LruCache<Integer, ChildProcessConnection> {
private final float mLowReduceRatio;
private final float mHighReduceRatio;
- private final Object mDelayedClearerLock = new Object();
private Runnable mDelayedClearer;
private final Handler mHandler = new Handler(ThreadUtils.getUiThreadLooper());
@@ -55,34 +62,9 @@ class BindingManagerImpl implements BindingManager {
mHighReduceRatio = highReduceRatio;
}
- @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();
- }
- }
- }
-
- @Override
- public void onLowMemory() {
- Log.i(TAG, "onLowMemory: evict %d bindings", size());
- evictAll();
- }
-
- @Override
- public void onConfigurationChanged(Configuration configuration) {}
-
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
- private void reduce(float reduceRatio) {
+ public void reduce(boolean useHighReduceRatio) {
+ final float reduceRatio = useHighReduceRatio ? mHighReduceRatio : mLowReduceRatio;
int oldSize = size();
int newSize = (int) (oldSize * (1f - reduceRatio));
Log.i(TAG, "Reduce connections from %d to %d", oldSize, newSize);
@@ -94,7 +76,7 @@ class BindingManagerImpl implements BindingManager {
// Entries will be removed from the front because snapshot() returns ones ordered
// from least recently accessed to most recently accessed.
int count = 0;
- for (Map.Entry<Integer, ManagedConnection> entry : snapshot().entrySet()) {
+ for (Map.Entry<Integer, ChildProcessConnection> entry : snapshot().entrySet()) {
remove(entry.getKey());
++count;
if (count == oldSize - newSize) break;
@@ -102,70 +84,84 @@ class BindingManagerImpl implements BindingManager {
}
}
- void addConnection(ManagedConnection managedConnection) {
- ChildProcessConnection connection = managedConnection.mConnection;
+ public void addConnection(ChildProcessConnection connection) {
if (connection != null && connection.isInSandbox()) {
- managedConnection.addModerateBinding();
+ addModerateBinding(connection);
if (connection.isModerateBindingBound()) {
- put(connection.getServiceNumber(), managedConnection);
+ put(connection.getServiceNumber(), connection);
} else {
remove(connection.getServiceNumber());
}
}
}
- void removeConnection(ManagedConnection managedConnection) {
- ChildProcessConnection connection = managedConnection.mConnection;
+ public void removeConnection(ChildProcessConnection connection) {
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();
- }
+ protected void entryRemoved(boolean evicted, Integer key, ChildProcessConnection oldValue,
+ ChildProcessConnection newValue) {
+ if (oldValue != newValue) removeModerateBinding(oldValue);
}
- void onSentToBackground(final boolean onTesting) {
+ public void onSentToBackground(final boolean onTesting) {
if (size() == 0) return;
- synchronized (mDelayedClearerLock) {
- mDelayedClearer = new Runnable() {
- @Override
- public void run() {
- synchronized (mDelayedClearerLock) {
+ mDelayedClearer = new Runnable() {
+ @Override
+ public void run() {
+ mLauncherThreadExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
if (mDelayedClearer == null) return;
mDelayedClearer = null;
+
+ Log.i(TAG, "Release moderate connections: %d", size());
+ if (!onTesting) {
+ RecordHistogram.recordCountHistogram(
+ "Android.ModerateBindingCount", size());
+ }
+ evictAll();
}
- Log.i(TAG, "Release moderate connections: %d", size());
- if (!onTesting) {
- RecordHistogram.recordCountHistogram(
- "Android.ModerateBindingCount", size());
- }
- evictAll();
- }
- };
- mHandler.postDelayed(mDelayedClearer, onTesting
- ? MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS_ON_TESTING
- : MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS);
- }
+ });
+ }
+ };
+ mHandler.postDelayed(mDelayedClearer, onTesting
+ ? MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS_ON_TESTING
+ : MODERATE_BINDING_POOL_CLEARER_DELAY_MILLIS);
}
- void onBroughtToForeground() {
- synchronized (mDelayedClearerLock) {
- if (mDelayedClearer == null) return;
- mHandler.removeCallbacks(mDelayedClearer);
- mDelayedClearer = null;
- }
+ public void onBroughtToForeground() {
+ if (mDelayedClearer == null) return;
+ mHandler.removeCallbacks(mDelayedClearer);
+ mDelayedClearer = null;
+ }
+
+ private void removeModerateBinding(ChildProcessConnection connection) {
+ if (connection == null || !connection.isModerateBindingBound()) return;
+ connection.removeModerateBinding();
+ }
+
+ private void addModerateBinding(ChildProcessConnection connection) {
+ if (connection == null) return;
+
+ connection.addModerateBinding();
}
}
- private final Object mModerateBindingPoolLock = new Object();
private ModerateBindingPool mModerateBindingPool;
/**
+ * Interface to listen to events related strong binding.
+ */
+ interface StrongBindingEventListener {
+ void onAdded(ChildProcessConnection managedConnection);
+ void onRemoved(ChildProcessConnection connection, boolean wasBoundForBackgroundPeriod);
+ }
+
+ /**
* Wraps ChildProcessConnection keeping track of additional information needed to manage the
* bindings of the connection. The reference to ChildProcessConnection is cleared when the
* connection goes away, but ManagedConnection itself is kept (until overwritten by a new entry
@@ -173,7 +169,7 @@ class BindingManagerImpl implements BindingManager {
*/
private class ManagedConnection {
// Set in constructor, cleared in clearConnection().
- private ChildProcessConnection mConnection;
+ private volatile ChildProcessConnection mConnection;
// True iff there is a strong binding kept on the service because it is working in
// foreground.
@@ -186,6 +182,8 @@ class BindingManagerImpl implements BindingManager {
// When mConnection is cleared, oom binding status is stashed here.
private boolean mWasOomProtected;
+ private StrongBindingEventListener mStrongBindingEventListener;
+
/** Removes the initial service binding. */
private void removeInitialBinding() {
if (mConnection == null || !mConnection.isInitialBindingBound()) return;
@@ -194,88 +192,66 @@ class BindingManagerImpl implements BindingManager {
/** Adds a strong service binding. */
private void addStrongBinding() {
- ChildProcessConnection connection = mConnection;
- if (connection == null) return;
+ if (mConnection == null) return;
- connection.addStrongBinding();
- ModerateBindingPool moderateBindingPool;
- synchronized (mModerateBindingPoolLock) {
- moderateBindingPool = mModerateBindingPool;
- }
- if (moderateBindingPool != null) moderateBindingPool.removeConnection(this);
+ mConnection.addStrongBinding();
+ mStrongBindingEventListener.onAdded(mConnection);
}
/** Removes a strong service binding. */
- private void removeStrongBinding(final boolean keepsAsModerate) {
- final ChildProcessConnection connection = mConnection;
+ private void removeStrongBinding(final boolean wasBoundForBackgroundPeriod) {
// 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.
- if (connection == null || !connection.isStrongBindingBound()) return;
+ if (mConnection == null || !mConnection.isStrongBindingBound()) return;
// 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()) {
- connection.removeStrongBinding();
- ModerateBindingPool moderateBindingPool;
- synchronized (mModerateBindingPoolLock) {
- moderateBindingPool = mModerateBindingPool;
- }
- if (moderateBindingPool != null && !connection.isStrongBindingBound()
- && keepsAsModerate) {
- moderateBindingPool.addConnection(ManagedConnection.this);
- }
- }
+ if (mConnection == null || !mConnection.isStrongBindingBound()) return;
+ mConnection.removeStrongBinding();
+ mStrongBindingEventListener.onRemoved(mConnection, wasBoundForBackgroundPeriod);
}
};
if (mIsLowMemoryDevice) {
doUnbind.run();
} else {
- ThreadUtils.postOnUiThreadDelayed(doUnbind, mRemoveStrongBindingDelay);
+ mLauncherThreadExecutor.executeDelayed(new Runnable() {
+ @Override
+ public void run() {
+ doUnbind.run();
+ }
+ }, mRemoveStrongBindingDelay);
}
}
- /** 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.
*/
- private void dropBindings() {
+ public void dropBindings() {
assert mIsLowMemoryDevice;
- ChildProcessConnection connection = mConnection;
- if (connection == null) return;
+ if (mConnection == null) return;
- connection.dropOomBindings();
+ mConnection.dropOomBindings();
}
- ManagedConnection(ChildProcessConnection connection) {
+ ManagedConnection(ChildProcessConnection connection,
+ StrongBindingEventListener strongBindingEventListener) {
mConnection = connection;
+ mStrongBindingEventListener = strongBindingEventListener;
}
/**
* Sets the visibility of the service, adding or removing the strong binding as needed.
*/
- void setInForeground(boolean nextInForeground) {
+ public void setInForeground(boolean nextInForeground) {
if (!mInForeground && nextInForeground) {
addStrongBinding();
} else if (mInForeground && !nextInForeground) {
- removeStrongBinding(true);
+ removeStrongBinding(false);
}
mInForeground = nextInForeground;
@@ -284,7 +260,7 @@ class BindingManagerImpl implements BindingManager {
/**
* Removes the initial binding.
*/
- void determinedVisibility() {
+ public void determinedVisibility() {
removeInitialBinding();
}
@@ -292,37 +268,39 @@ class BindingManagerImpl implements BindingManager {
* Sets or removes additional binding when the service is main service during the embedder
* background period.
*/
- void setBoundForBackgroundPeriod(boolean nextBound) {
+ public void setBoundForBackgroundPeriod(boolean nextBound) {
if (!mBoundForBackgroundPeriod && nextBound) {
addStrongBinding();
} else if (mBoundForBackgroundPeriod && !nextBound) {
- removeStrongBinding(false);
+ removeStrongBinding(true);
}
mBoundForBackgroundPeriod = nextBound;
}
- boolean isOomProtected() {
+ /** This may be called from any thread. */
+ public boolean isOomProtected() {
// When a process crashes, we can be queried about its oom status before or after the
// connection is cleared. For the latter case, the oom status is stashed in
// mWasOomProtected.
- return mConnection != null
- ? mConnection.isOomProtectedOrWasWhenDied() : mWasOomProtected;
+ ChildProcessConnection connection = mConnection;
+ if (connection == null) return mWasOomProtected;
+
+ return connection.isOomProtectedOrWasWhenDied();
}
- void clearConnection() {
+ public void clearConnection() {
+ if (mConnection == null) return;
mWasOomProtected = mConnection.isOomProtectedOrWasWhenDied();
- ModerateBindingPool moderateBindingPool;
- synchronized (mModerateBindingPoolLock) {
- moderateBindingPool = mModerateBindingPool;
- }
- if (moderateBindingPool != null) moderateBindingPool.removeConnection(this);
mConnection = null;
}
- /** @return true iff the reference to the connection is no longer held */
+ /**
+ * This may be called from any thread.
+ * @return true iff the reference to the connection is no longer held
+ */
@VisibleForTesting
- boolean isConnectionCleared() {
+ public boolean isConnectionCleared() {
return mConnection == null;
}
}
@@ -337,30 +315,47 @@ class BindingManagerImpl implements BindingManager {
// renderer process at a time is protected from oom killing.
private ManagedConnection mLastInForeground;
- // Synchronizes operations that access mLastInForeground: setInForeground() and
- // addNewConnection().
- private final Object mLastInForegroundLock = new Object();
-
// The connection bound with additional binding in onSentToBackground().
private ManagedConnection mBoundForBackgroundPeriod;
// Whether this instance is used on testing.
private final boolean mOnTesting;
+ // Executor that executes a task on LauncherThread.
+ private final LauncherThreadExecutor mLauncherThreadExecutor;
+
+ private final Object mThreadIdLock = new Object();
+ private Long mThreadId;
+
+ void checkCalledOnProcessLauncherThread() {
+ if (mOnTesting) return;
+
+ synchronized (mThreadIdLock) {
+ long currentThreadId = Thread.currentThread().getId();
+ if (mThreadId == null) {
+ mThreadId = currentThreadId;
+ } else if (mThreadId != currentThreadId) {
+ throw new IllegalStateException(
+ "Method is not called on valid thread: " + Thread.currentThread());
+ }
+ }
+ }
+
/**
* 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,20 +364,56 @@ 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) {
+ ThreadUtils.runOnUiThread(runnable);
+ }
+
+ @Override
+ public void executeDelayed(Runnable runnable, long delayInMS) {
+ ThreadUtils.postOnUiThreadDelayed(runnable, delayInMS);
+ }
+ };
+ return new BindingManagerImpl(isLowEndDevice, 0, true, executor);
}
@Override
public void addNewConnection(int pid, ChildProcessConnection connection) {
+ checkCalledOnProcessLauncherThread();
+
// This will reset the previous entry for the pid in the unlikely event of the OS
// reusing renderer pids.
synchronized (mManagedConnections) {
- mManagedConnections.put(pid, new ManagedConnection(connection));
+ StrongBindingEventListener listener = new StrongBindingEventListener() {
+ @Override
+ public void onAdded(ChildProcessConnection connection) {
+ checkCalledOnProcessLauncherThread();
+
+ if (mModerateBindingPool != null) {
+ mModerateBindingPool.removeConnection(connection);
+ }
+ }
+
+ @Override
+ public void onRemoved(
+ ChildProcessConnection connection, boolean wasBoundForBackgroundPeriod) {
+ checkCalledOnProcessLauncherThread();
+
+ if (mModerateBindingPool != null && !connection.isStrongBindingBound()
+ && !wasBoundForBackgroundPeriod) {
+ mModerateBindingPool.addConnection(connection);
+ }
+ }
+ };
+ mManagedConnections.put(pid, new ManagedConnection(connection, listener));
}
}
@Override
public void setInForeground(int pid, boolean inForeground) {
+ checkCalledOnProcessLauncherThread();
+
ManagedConnection managedConnection;
synchronized (mManagedConnections) {
managedConnection = mManagedConnections.get(pid);
@@ -393,19 +424,19 @@ class BindingManagerImpl implements BindingManager {
return;
}
- synchronized (mLastInForegroundLock) {
- if (inForeground && mIsLowMemoryDevice && mLastInForeground != null
- && mLastInForeground != managedConnection) {
- mLastInForeground.dropBindings();
- }
-
- managedConnection.setInForeground(inForeground);
- if (inForeground) mLastInForeground = managedConnection;
+ if (inForeground && mIsLowMemoryDevice && mLastInForeground != null
+ && mLastInForeground != managedConnection) {
+ mLastInForeground.dropBindings();
}
+
+ managedConnection.setInForeground(inForeground);
+ if (inForeground) mLastInForeground = managedConnection;
}
@Override
public void determinedVisibility(int pid) {
+ checkCalledOnProcessLauncherThread();
+
ManagedConnection managedConnection;
synchronized (mManagedConnections) {
managedConnection = mManagedConnections.get(pid);
@@ -422,35 +453,32 @@ class BindingManagerImpl implements BindingManager {
@Override
public void onSentToBackground() {
+ checkCalledOnProcessLauncherThread();
+
assert mBoundForBackgroundPeriod == null;
- synchronized (mLastInForegroundLock) {
- // mLastInForeground can be null at this point as the embedding application could be
- // used in foreground without spawning any renderers.
- if (mLastInForeground != null) {
- mLastInForeground.setBoundForBackgroundPeriod(true);
- mBoundForBackgroundPeriod = mLastInForeground;
- }
- }
- ModerateBindingPool moderateBindingPool;
- synchronized (mModerateBindingPoolLock) {
- moderateBindingPool = mModerateBindingPool;
+
+ // mLastInForeground can be null at this point as the embedding application could be
+ // used in foreground without spawning any renderers.
+ if (mLastInForeground != null) {
+ mLastInForeground.setBoundForBackgroundPeriod(true);
+ mBoundForBackgroundPeriod = mLastInForeground;
}
- if (moderateBindingPool != null) moderateBindingPool.onSentToBackground(mOnTesting);
+
+ if (mModerateBindingPool != null) mModerateBindingPool.onSentToBackground(mOnTesting);
}
@Override
public void onBroughtToForeground() {
+ checkCalledOnProcessLauncherThread();
+
if (mBoundForBackgroundPeriod != null) {
mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false);
mBoundForBackgroundPeriod = null;
}
- ModerateBindingPool moderateBindingPool;
- synchronized (mModerateBindingPoolLock) {
- moderateBindingPool = mModerateBindingPool;
- }
- if (moderateBindingPool != null) moderateBindingPool.onBroughtToForeground();
+ if (mModerateBindingPool != null) mModerateBindingPool.onBroughtToForeground();
}
+ /** This may be called from any thread. */
@Override
public boolean isOomProtected(int pid) {
// In the unlikely event of the OS reusing renderer pid, the call will refer to the most
@@ -465,44 +493,93 @@ class BindingManagerImpl implements BindingManager {
@Override
public void clearConnection(int pid) {
+ checkCalledOnProcessLauncherThread();
+
ManagedConnection managedConnection;
synchronized (mManagedConnections) {
managedConnection = mManagedConnections.get(pid);
}
- if (managedConnection != null) managedConnection.clearConnection();
+ // TODO: we need to find a way to clean up dead connections in mManagedConnections.
+ if (managedConnection != null) {
+ if (mModerateBindingPool != null) {
+ mModerateBindingPool.removeConnection(managedConnection.mConnection);
+ }
+ managedConnection.clearConnection();
+ }
}
- /** @return true iff the connection reference is no longer held */
+ /**
+ * This may be called from any thread.
+ * @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();
}
}
@Override
public void startModerateBindingManagement(
Context context, int maxSize, float lowReduceRatio, float highReduceRatio) {
- synchronized (mModerateBindingPoolLock) {
- if (mIsLowMemoryDevice || mModerateBindingPool != null) return;
+ checkCalledOnProcessLauncherThread();
+
+ if (mIsLowMemoryDevice || mModerateBindingPool != null) return;
+
+ Log.i(TAG, "Moderate binding enabled: maxSize=%d lowReduceRatio=%f highReduceRatio=%f",
+ maxSize, lowReduceRatio, highReduceRatio);
+ mModerateBindingPool = new ModerateBindingPool(maxSize, lowReduceRatio, highReduceRatio);
+ if (context != null) {
+ context.registerComponentCallbacks(new ComponentCallbacks2() {
+ @Override
+ public void onTrimMemory(final int level) {
+ mLauncherThreadExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ Log.i(TAG, "onTrimMemory: level=%d, size=%d", level,
+ mModerateBindingPool.size());
+ if (mModerateBindingPool.size() > 0) {
+ if (level <= TRIM_MEMORY_RUNNING_MODERATE) {
+ mModerateBindingPool.reduce(false);
+ } else if (level <= TRIM_MEMORY_RUNNING_LOW) {
+ mModerateBindingPool.reduce(true);
+ } else if (level == TRIM_MEMORY_UI_HIDDEN) {
+ // This will be handled by onSentToBackground().
+ return;
+ } else {
+ mModerateBindingPool.evictAll();
+ }
+ }
+ }
+ });
+ }
- Log.i(TAG, "Moderate binding enabled: maxSize=%d lowReduceRatio=%f highReduceRatio=%f",
- maxSize, lowReduceRatio, highReduceRatio);
- mModerateBindingPool =
- new ModerateBindingPool(maxSize, lowReduceRatio, highReduceRatio);
- if (context != null) context.registerComponentCallbacks(mModerateBindingPool);
+ @Override
+ public void onLowMemory() {
+ mLauncherThreadExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ Log.i(TAG, "onLowMemory: evict %d bindings",
+ mModerateBindingPool.size());
+ mModerateBindingPool.evictAll();
+ }
+ });
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration configuration) {}
+ });
}
}
@Override
public void releaseAllModerateBindings() {
- ModerateBindingPool moderateBindingPool;
- synchronized (mModerateBindingPoolLock) {
- moderateBindingPool = mModerateBindingPool;
- }
- if (moderateBindingPool != null) {
- Log.i(TAG, "Release all moderate bindings: %d", moderateBindingPool.size());
- moderateBindingPool.evictAll();
+ checkCalledOnProcessLauncherThread();
+
+ if (mModerateBindingPool != null) {
+ Log.i(TAG, "Release all moderate bindings: %d", mModerateBindingPool.size());
+ mModerateBindingPool.evictAll();
}
}
}

Powered by Google App Engine
This is Rietveld 408576698