This source file includes following definitions.
- removeInitialBinding
- addStrongBinding
- removeStrongBinding
- dropBindings
- setInForeground
- setBoundForBackgroundPeriod
- isOomProtected
- clearConnection
- isConnectionCleared
- createBindingManager
- createBindingManagerForTesting
- addNewConnection
- setInForeground
- onSentToBackground
- onBroughtToForeground
- isOomProtected
- clearConnection
- isConnectionCleared
package org.chromium.content.browser;
import android.util.Log;
import android.util.SparseArray;
import com.google.common.annotations.VisibleForTesting;
import org.chromium.base.SysUtils;
import org.chromium.base.ThreadUtils;
class BindingManagerImpl implements BindingManager {
private static final String TAG = "BindingManager";
private static final long REMOVE_INITIAL_BINDING_DELAY_MILLIS = 1 * 1000;
private static final long DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS = 1 * 1000;
private final long mRemoveInitialBindingDelay;
private final long mRemoveStrongBindingDelay;
private final boolean mIsLowMemoryDevice;
private class ManagedConnection {
private ChildProcessConnection mConnection;
private boolean mInForeground;
private boolean mBoundForBackgroundPeriod;
private boolean mWasOomProtected;
private void removeInitialBinding() {
final ChildProcessConnection connection = mConnection;
if (connection == null || !connection.isInitialBindingBound()) return;
ThreadUtils.postOnUiThreadDelayed(new Runnable() {
@Override
public void run() {
if (connection.isInitialBindingBound()) {
connection.removeInitialBinding();
}
}
}, mRemoveInitialBindingDelay);
}
private void addStrongBinding() {
ChildProcessConnection connection = mConnection;
if (connection == null) return;
connection.addStrongBinding();
}
private void removeStrongBinding() {
final ChildProcessConnection connection = mConnection;
if (connection == null || !connection.isStrongBindingBound()) return;
Runnable doUnbind = new Runnable() {
@Override
public void run() {
if (connection.isStrongBindingBound()) {
connection.removeStrongBinding();
}
}
};
if (mIsLowMemoryDevice) {
doUnbind.run();
} else {
ThreadUtils.postOnUiThreadDelayed(doUnbind, mRemoveStrongBindingDelay);
}
}
private void dropBindings() {
assert mIsLowMemoryDevice;
ChildProcessConnection connection = mConnection;
if (connection == null) return;
connection.dropOomBindings();
}
ManagedConnection(ChildProcessConnection connection) {
mConnection = connection;
}
void setInForeground(boolean nextInForeground) {
if (!mInForeground && nextInForeground) {
addStrongBinding();
} else if (mInForeground && !nextInForeground) {
removeStrongBinding();
}
removeInitialBinding();
mInForeground = nextInForeground;
}
void setBoundForBackgroundPeriod(boolean nextBound) {
if (!mBoundForBackgroundPeriod && nextBound) {
addStrongBinding();
} else if (mBoundForBackgroundPeriod && !nextBound) {
removeStrongBinding();
}
mBoundForBackgroundPeriod = nextBound;
}
boolean isOomProtected() {
return mConnection != null ?
mConnection.isOomProtectedOrWasWhenDied() : mWasOomProtected;
}
void clearConnection() {
mWasOomProtected = mConnection.isOomProtectedOrWasWhenDied();
mConnection = null;
}
@VisibleForTesting
boolean isConnectionCleared() {
return mConnection == null;
}
}
private final SparseArray<ManagedConnection> mManagedConnections =
new SparseArray<ManagedConnection>();
private ManagedConnection mLastInForeground;
private final Object mLastInForegroundLock = new Object();
private ManagedConnection mBoundForBackgroundPeriod;
private BindingManagerImpl(boolean isLowMemoryDevice, long removeInitialBindingDelay,
long removeStrongBindingDelay) {
mIsLowMemoryDevice = isLowMemoryDevice;
mRemoveInitialBindingDelay = removeInitialBindingDelay;
mRemoveStrongBindingDelay = removeStrongBindingDelay;
}
public static BindingManagerImpl createBindingManager() {
return new BindingManagerImpl(SysUtils.isLowEndDevice(),
REMOVE_INITIAL_BINDING_DELAY_MILLIS, DETACH_AS_ACTIVE_HIGH_END_DELAY_MILLIS);
}
public static BindingManagerImpl createBindingManagerForTesting(boolean isLowEndDevice) {
return new BindingManagerImpl(isLowEndDevice, 0, 0);
}
@Override
public void addNewConnection(int pid, ChildProcessConnection connection) {
synchronized (mLastInForegroundLock) {
if (mIsLowMemoryDevice && mLastInForeground != null) mLastInForeground.dropBindings();
}
synchronized (mManagedConnections) {
mManagedConnections.put(pid, new ManagedConnection(connection));
}
}
@Override
public void setInForeground(int pid, boolean inForeground) {
ManagedConnection managedConnection;
synchronized (mManagedConnections) {
managedConnection = mManagedConnections.get(pid);
}
if (managedConnection == null) {
Log.w(TAG, "Cannot setInForeground() - never saw a connection for the pid: " +
Integer.toString(pid));
return;
}
synchronized (mLastInForegroundLock) {
managedConnection.setInForeground(inForeground);
if (inForeground) mLastInForeground = managedConnection;
}
}
@Override
public void onSentToBackground() {
assert mBoundForBackgroundPeriod == null;
synchronized (mLastInForegroundLock) {
if (mLastInForeground != null) {
mLastInForeground.setBoundForBackgroundPeriod(true);
mBoundForBackgroundPeriod = mLastInForeground;
}
}
}
@Override
public void onBroughtToForeground() {
if (mBoundForBackgroundPeriod != null) {
mBoundForBackgroundPeriod.setBoundForBackgroundPeriod(false);
mBoundForBackgroundPeriod = null;
}
}
@Override
public boolean isOomProtected(int pid) {
ManagedConnection managedConnection;
synchronized (mManagedConnections) {
managedConnection = mManagedConnections.get(pid);
}
return managedConnection != null ? managedConnection.isOomProtected() : false;
}
@Override
public void clearConnection(int pid) {
ManagedConnection managedConnection;
synchronized (mManagedConnections) {
managedConnection = mManagedConnections.get(pid);
}
if (managedConnection != null) managedConnection.clearConnection();
}
@VisibleForTesting
public boolean isConnectionCleared(int pid) {
synchronized (mManagedConnections) {
return mManagedConnections.get(pid).isConnectionCleared();
}
}
}