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

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

Issue 2828793002: Refactoring ChildProcessConnection. (Closed)
Patch Set: More test fixing. Created 3 years, 8 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/BaseChildProcessConnection.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java b/content/public/android/java/src/org/chromium/content/browser/BaseChildProcessConnection.java
similarity index 61%
rename from content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
rename to content/public/android/java/src/org/chromium/content/browser/BaseChildProcessConnection.java
index 710741b69c86a045512bf88f0459e6b9fd7934e7..52bfe5e5a7876a9868afff7493a07b436c6e7a19 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/BaseChildProcessConnection.java
@@ -26,97 +26,72 @@ import org.chromium.base.process_launcher.IChildProcessService;
import java.io.IOException;
import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
/**
* Manages a connection between the browser activity and a child service.
*/
-public class ChildProcessConnectionImpl implements ChildProcessConnection {
- private final Context mContext;
- private final int mServiceNumber;
- private final boolean mInSandbox;
- private final ChildProcessConnection.DeathCallback mDeathCallback;
- private final ComponentName mServiceName;
-
- // Synchronization: While most internal flow occurs on the UI thread, the public API
- // (specifically start and stop) may be called from any thread, hence all entry point methods
- // into the class are synchronized on the lock to protect access to these members.
- private final Object mLock = new Object();
- private IChildProcessService mService;
- // Set to true when the service connection callback runs. This differs from
- // mServiceConnectComplete, which tracks that the connection completed successfully.
- private boolean mDidOnServiceConnected;
- // Set to true when the service connected successfully.
- private boolean mServiceConnectComplete;
- // Set to true when the service disconnects, as opposed to being properly closed. This happens
- // when the process crashes or gets killed by the system out-of-memory killer.
- private boolean mServiceDisconnected;
- // When the service disconnects (i.e. mServiceDisconnected is set to true), the status of the
- // oom bindings is stashed here for future inspection.
- private boolean mWasOomProtected;
- private int mPid; // Process ID of the corresponding child process.
- // Initial binding protects the newly spawned process from being killed before it is put to use,
- // it is maintained between calls to start() and removeInitialBinding().
- private ChildServiceConnection mInitialBinding;
- // Strong binding will make the service priority equal to the priority of the activity. We want
- // the OS to be able to kill background renderers as it kills other background apps, so strong
- // bindings are maintained only for services that are active at the moment (between
- // addStrongBinding() and removeStrongBinding()).
- private ChildServiceConnection mStrongBinding;
- // Low priority binding maintained in the entire lifetime of the connection, i.e. between calls
- // to start() and stop().
- private ChildServiceConnection mWaivedBinding;
- // Incremented on addStrongBinding(), decremented on removeStrongBinding().
- private int mStrongBindingCount;
- // Moderate binding will make the service priority equal to the priority of a visible process
- // while the app is in the foreground. It will stay bound only while the app is in the
- // foreground to protect a background process from the system out-of-memory killer.
- private ChildServiceConnection mModerateBinding;
-
- // Parameters passed to the child process through the service binding intent.
- // If the service gets recreated by the framework the intent will be reused, so these parameters
- // should be common to all processes of that type.
- private final Bundle mChildProcessCommonParameters;
-
- private final boolean mAlwaysInForeground;
- private final ChildProcessCreationParams mCreationParams;
+public abstract class BaseChildProcessConnection {
+ private static final String TAG = "BaseChildProcessConn";
- // Caches whether non-sandboxed and sandboxed services require an extra
- // binding flag provided via ChildProcessCreationParams.
- // TODO(mnaganov): Get rid of it after the release of the next Android SDK.
- private static Boolean sNeedsExtrabindFlags[] = new Boolean[2];
-
- private static final String TAG = "ChildProcessConnect";
-
- private static class ConnectionParams {
- final String[] mCommandLine;
- final FileDescriptorInfo[] mFilesToBeMapped;
- final IBinder mCallback;
-
- ConnectionParams(
- String[] commandLine, FileDescriptorInfo[] filesToBeMapped, IBinder callback) {
- mCommandLine = commandLine;
- mFilesToBeMapped = filesToBeMapped;
- mCallback = callback;
- }
+ /**
+ * Used to notify the consumer about disconnection of the service. This callback is provided
+ * earlier than ConnectionCallbacks below, as a child process might die before the connection is
+ * fully set up.
+ */
+ interface DeathCallback {
+ // Called on Launcher thread.
+ void onChildProcessDied(BaseChildProcessConnection connection);
}
- // This is set in start() and is used in onServiceConnected().
- private ChildProcessConnection.StartCallback mStartCallback;
+ /**
+ * Used to notify the consumer about the process start. These callbacks will be invoked before
+ * the ConnectionCallbacks.
+ */
+ interface StartCallback {
+ /**
+ * Called when the child process has successfully started and is ready for connection
+ * setup.
+ */
+ void onChildStarted();
+
+ /**
+ * Called when the child process failed to start. This can happen if the process is already
+ * in use by another client.
+ */
+ void onChildStartFailed();
+ }
- // This is set in setupConnection() and is later used in doConnectionSetupLocked(), after which
- // the variable is cleared. Therefore this is only valid while the connection is being set up.
- private ConnectionParams mConnectionParams;
+ /**
+ * Used to notify the consumer about the connection being established.
+ */
+ interface ConnectionCallback {
+ /**
+ * Called when the connection to the service is established.
+ * @param connecion the connection object to the child process
+ */
+ void onConnected(BaseChildProcessConnection connection);
+ }
- // Callback provided in setupConnection() that will communicate the result to the caller. This
- // has to be called exactly once after setupConnection(), even if setup fails, so that the
- // caller can free up resources associated with the setup attempt. This is set to null after the
- // call.
- private ChildProcessConnection.ConnectionCallback mConnectionCallback;
+ /** Used to create specialization connection instances. */
+ interface Factory {
+ BaseChildProcessConnection create(Context context, int number, boolean sandboxed,
+ DeathCallback deathCallback, String serviceClassName,
+ Bundle childProcessCommonParameters, ChildProcessCreationParams creationParams);
+ }
- private class ChildServiceConnection implements ServiceConnection {
- private boolean mBound;
+ /** Interface representing a connection to the Android service. Can be mocked in unit-tests. */
+ protected interface ChildServiceConnection {
+ boolean bind();
+ void unbind();
+ boolean isBound();
+ }
+ /** Implementation of ChildServiceConnection that does connect to a service. */
+ protected class ChildServiceConnectionImpl
+ implements ChildServiceConnection, ServiceConnection {
private final int mBindFlags;
+ private boolean mBound;
private Intent createServiceBindIntent() {
Intent intent = new Intent();
@@ -127,34 +102,37 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
return intent;
}
- public ChildServiceConnection(int bindFlags) {
+ private ChildServiceConnectionImpl(int bindFlags) {
mBindFlags = bindFlags;
}
- boolean bind() {
+ @Override
+ public boolean bind() {
if (!mBound) {
try {
- TraceEvent.begin("ChildProcessConnectionImpl.ChildServiceConnection.bind");
+ TraceEvent.begin("BaseChildProcessConnection.ChildServiceConnection.bind");
Intent intent = createServiceBindIntent();
if (mChildProcessCommonParameters != null) {
intent.putExtras(mChildProcessCommonParameters);
}
mBound = mContext.bindService(intent, this, mBindFlags);
} finally {
- TraceEvent.end("ChildProcessConnectionImpl.ChildServiceConnection.bind");
+ TraceEvent.end("BaseChildProcessConnection.ChildServiceConnection.bind");
}
}
return mBound;
}
- void unbind() {
+ @Override
+ public void unbind() {
if (mBound) {
mContext.unbindService(this);
mBound = false;
}
}
- boolean isBound() {
+ @Override
+ public boolean isBound() {
return mBound;
}
@@ -163,7 +141,7 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
LauncherThread.post(new Runnable() {
@Override
public void run() {
- ChildProcessConnectionImpl.this.onServiceConnectedOnLauncherThread(service);
+ BaseChildProcessConnection.this.onServiceConnectedOnLauncherThread(service);
}
});
}
@@ -174,123 +152,178 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
LauncherThread.post(new Runnable() {
@Override
public void run() {
- ChildProcessConnectionImpl.this.onServiceDisconnectedOnLauncherThread();
+ BaseChildProcessConnection.this.onServiceDisconnectedOnLauncherThread();
}
});
}
}
- ChildProcessConnectionImpl(Context context, int number, boolean inSandbox,
- ChildProcessConnection.DeathCallback deathCallback, String serviceClassName,
- Bundle childProcessCommonParameters, boolean alwaysInForeground,
- ChildProcessCreationParams creationParams) {
+ // Caches whether non-sandboxed and sandboxed services require an extra
+ // binding flag provided via ChildProcessCreationParams.
+ // TODO(mnaganov): Get rid of it after the release of the next Android SDK.
+ private static Boolean sNeedsExtrabindFlags[] = new Boolean[2];
+ private final Context mContext;
+ private final int mServiceNumber;
+ private final boolean mSandboxed;
+ private final BaseChildProcessConnection.DeathCallback mDeathCallback;
+ private final ComponentName mServiceName;
+
+ // Parameters passed to the child process through the service binding intent.
+ // If the service gets recreated by the framework the intent will be reused, so these parameters
+ // should be common to all processes of that type.
+ private final Bundle mChildProcessCommonParameters;
+
+ private final ChildProcessCreationParams mCreationParams;
+
+ private static class ConnectionParams {
+ final String[] mCommandLine;
+ final FileDescriptorInfo[] mFilesToBeMapped;
+ final IBinder mCallback;
+
+ ConnectionParams(
+ String[] commandLine, FileDescriptorInfo[] filesToBeMapped, IBinder callback) {
+ mCommandLine = commandLine;
+ mFilesToBeMapped = filesToBeMapped;
+ mCallback = callback;
+ }
+ }
+
+ // Synchronization: While most internal flow occurs on the UI thread, the public API
+ // (specifically start and stop) may be called from any thread, hence all entry point methods
+ // into the class are synchronized on the lock to protect access to these members.
+ // TODO(jcivelli): crbug.com/714657 remove this lock.
+ private final Object mLock = new Object();
+
+ // This is set in start() and is used in onServiceConnected().
+ @GuardedBy("mLock")
+ private StartCallback mStartCallback;
+
+ // This is set in setupConnection() and is later used in doConnectionSetupLocked(), after which
+ // the variable is cleared. Therefore this is only valid while the connection is being set up.
+ @GuardedBy("mLock")
+ private ConnectionParams mConnectionParams;
+
+ // Callback provided in setupConnection() that will communicate the result to the caller. This
+ // has to be called exactly once after setupConnection(), even if setup fails, so that the
+ // caller can free up resources associated with the setup attempt. This is set to null after the
+ // call.
+ @GuardedBy("mLock")
+ private ConnectionCallback mConnectionCallback;
+
+ @GuardedBy("mLock")
+ private IChildProcessService mService;
+
+ // Set to true when the service connection callback runs. This differs from
+ // mServiceConnectComplete, which tracks that the connection completed successfully.
+ @GuardedBy("mLock")
+ private boolean mDidOnServiceConnected;
+
+ // Set to true when the service connected successfully.
+ @GuardedBy("mLock")
+ private boolean mServiceConnectComplete;
+
+ // Set to true when the service disconnects, as opposed to being properly closed. This happens
+ // when the process crashes or gets killed by the system out-of-memory killer.
+ @GuardedBy("mLock")
+ private boolean mServiceDisconnected;
+
+ // Process ID of the corresponding child process.
+ @GuardedBy("mLock")
+ private int mPid;
+
+ protected BaseChildProcessConnection(Context context, int number, boolean sandboxed,
+ DeathCallback deathCallback, String serviceClassName,
+ Bundle childProcessCommonParameters, ChildProcessCreationParams creationParams) {
mContext = context;
mServiceNumber = number;
- mInSandbox = inSandbox;
+ mSandboxed = sandboxed;
mDeathCallback = deathCallback;
String packageName =
creationParams != null ? creationParams.getPackageName() : context.getPackageName();
mServiceName = new ComponentName(packageName, serviceClassName + mServiceNumber);
mChildProcessCommonParameters = childProcessCommonParameters;
- mAlwaysInForeground = alwaysInForeground;
mCreationParams = creationParams;
- int initialFlags = Context.BIND_AUTO_CREATE;
- if (mAlwaysInForeground) initialFlags |= Context.BIND_IMPORTANT;
- int extraBindFlags = 0;
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && mCreationParams != null
- && mCreationParams.getIsExternalService()
- && isExportedService(inSandbox, mContext, mServiceName)) {
- extraBindFlags = Context.BIND_EXTERNAL_SERVICE;
- }
- mInitialBinding = new ChildServiceConnection(initialFlags | extraBindFlags);
- mStrongBinding = new ChildServiceConnection(
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT | extraBindFlags);
- mWaivedBinding = new ChildServiceConnection(
- Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY | extraBindFlags);
- mModerateBinding = new ChildServiceConnection(Context.BIND_AUTO_CREATE | extraBindFlags);
}
- private static boolean isExportedService(boolean inSandbox, Context context,
- ComponentName serviceName) {
- // Check for the cached value first. It is assumed that all pooled child services
- // have identical attributes in the manifest.
- final int arrayIndex = inSandbox ? 1 : 0;
- if (sNeedsExtrabindFlags[arrayIndex] != null) {
- return sNeedsExtrabindFlags[arrayIndex].booleanValue();
- }
- boolean result = false;
- try {
- PackageManager packageManager = context.getPackageManager();
- ServiceInfo serviceInfo = packageManager.getServiceInfo(serviceName, 0);
- result = serviceInfo.exported;
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(TAG, "Could not retrieve info about service %s", serviceName, e);
- }
- sNeedsExtrabindFlags[arrayIndex] = Boolean.valueOf(result);
- return result;
+ public final Context getContext() {
+ return mContext;
}
- @Override
- public int getServiceNumber() {
+ public final int getServiceNumber() {
return mServiceNumber;
}
- @Override
- public boolean isInSandbox() {
- return mInSandbox;
+ public final boolean isSandboxed() {
+ return mSandboxed;
}
- @Override
- public String getPackageName() {
+ public final String getPackageName() {
return mCreationParams != null ? mCreationParams.getPackageName()
- : mContext.getPackageName();
+ : mContext.getPackageName();
}
- @Override
- public ChildProcessCreationParams getCreationParams() {
+ public final ChildProcessCreationParams getCreationParams() {
return mCreationParams;
}
- @Override
- public IChildProcessService getService() {
+ public final IChildProcessService getService() {
synchronized (mLock) {
return mService;
}
}
- @Override
+ public final ComponentName getServiceName() {
+ return mServiceName;
+ }
+
+ /**
+ * @return the connection pid, or 0 if not yet connected
+ */
public int getPid() {
synchronized (mLock) {
return mPid;
}
}
- @Override
- public void start(ChildProcessConnection.StartCallback startCallback) {
+ /**
+ * Starts a connection to an IChildProcessService. This must be followed by a call to
+ * setupConnection() to setup the connection parameters. start() and setupConnection() are
+ * separate to allow to pass whatever parameters are available in start(), and complete the
+ * remainder later while reducing the connection setup latency.
+ * @param startCallback (optional) callback when the child process starts or fails to start.
+ */
+ public void start(StartCallback startCallback) {
try {
- TraceEvent.begin("ChildProcessConnectionImpl.start");
+ TraceEvent.begin("BaseChildProcessConnection.start");
assert LauncherThread.runningOnLauncherThread();
synchronized (mLock) {
- assert mConnectionParams == null :
- "setupConnection() called before start() in ChildProcessConnectionImpl.";
+ assert mConnectionParams
+ == null
+ : "setupConnection() called before start() in BaseChildProcessConnection.";
mStartCallback = startCallback;
- if (!mInitialBinding.bind()) {
+ if (!bind()) {
Log.e(TAG, "Failed to establish the service connection.");
// We have to notify the caller so that they can free-up associated resources.
// TODO(ppi): Can we hard-fail here?
- mDeathCallback.onChildProcessDied(ChildProcessConnectionImpl.this);
- } else {
- mWaivedBinding.bind();
+ mDeathCallback.onChildProcessDied(BaseChildProcessConnection.this);
}
}
} finally {
- TraceEvent.end("ChildProcessConnectionImpl.start");
+ TraceEvent.end("BaseChildProcessConnection.start");
}
}
- @Override
+ /**
+ * Setups the connection after it was started with start().
+ * @param commandLine (optional) will be ignored if the command line was already sent in start()
+ * @param filesToBeMapped a list of file descriptors that should be registered
+ * @param callback optional client specified callbacks that the child can use to communicate
+ * with the parent process
+ * @param connectionCallback will be called exactly once after the connection is set up or the
+ * setup fails
+ */
public void setupConnection(String[] commandLine, FileDescriptorInfo[] filesToBeMapped,
@Nullable IBinder callback, ConnectionCallback connectionCallback) {
assert LauncherThread.runningOnLauncherThread();
@@ -298,11 +331,11 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
assert mConnectionParams == null;
if (mServiceDisconnected) {
Log.w(TAG, "Tried to setup a connection that already disconnected.");
- connectionCallback.onConnected(0);
+ connectionCallback.onConnected(null);
return;
}
try {
- TraceEvent.begin("ChildProcessConnectionImpl.setupConnection");
+ TraceEvent.begin("BaseChildProcessConnection.setupConnection");
mConnectionCallback = connectionCallback;
mConnectionParams = new ConnectionParams(commandLine, filesToBeMapped, callback);
// Run the setup if the service is already connected. If not,
@@ -311,22 +344,19 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
doConnectionSetupLocked();
}
} finally {
- TraceEvent.end("ChildProcessConnectionImpl.setupConnection");
+ TraceEvent.end("BaseChildProcessConnection.setupConnection");
}
}
}
- @Override
+ /**
+ * Terminates the connection to IChildProcessService, closing all bindings. It is safe to call
+ * this multiple times.
+ */
public void stop() {
synchronized (mLock) {
- mInitialBinding.unbind();
- mStrongBinding.unbind();
- mWaivedBinding.unbind();
- mModerateBinding.unbind();
- mStrongBindingCount = 0;
- if (mService != null) {
- mService = null;
- }
+ unbind();
+ mService = null;
mConnectionParams = null;
}
}
@@ -341,7 +371,7 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
}
try {
TraceEvent.begin(
- "ChildProcessConnectionImpl.ChildServiceConnection.onServiceConnected");
+ "BaseChildProcessConnection.ChildServiceConnection.onServiceConnected");
mDidOnServiceConnected = true;
mService = IChildProcessService.Stub.asInterface(service);
@@ -381,7 +411,7 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
}
} finally {
TraceEvent.end(
- "ChildProcessConnectionImpl.ChildServiceConnection.onServiceConnected");
+ "BaseChildProcessConnection.ChildServiceConnection.onServiceConnected");
}
}
}
@@ -394,16 +424,14 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
if (mServiceDisconnected) {
return;
}
- // Stash the status of the oom bindings, since stop() will release all bindings.
- mWasOomProtected = isCurrentlyOomProtected();
mServiceDisconnected = true;
Log.w(TAG, "onServiceDisconnected (crash or killed by oom): pid=%d", mPid);
stop(); // We don't want to auto-restart on crash. Let the browser do that.
- mDeathCallback.onChildProcessDied(ChildProcessConnectionImpl.this);
+ mDeathCallback.onChildProcessDied(BaseChildProcessConnection.this);
// If we have a pending connection callback, we need to communicate the failure to
// the caller.
if (mConnectionCallback != null) {
- mConnectionCallback.onConnected(0);
+ mConnectionCallback.onConnected(null);
}
mConnectionCallback = null;
}
@@ -415,7 +443,7 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
assert mPid != 0 : "Child service claims to be run by a process of pid=0.";
if (mConnectionCallback != null) {
- mConnectionCallback.onConnected(mPid);
+ mConnectionCallback.onConnected(this);
}
mConnectionCallback = null;
}
@@ -426,9 +454,10 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
* connection has been established (as signaled by onServiceConnected()). These two events can
* happen in any order. Has to be called with mLock.
*/
+ @GuardedBy("mLock")
private void doConnectionSetupLocked() {
try {
- TraceEvent.begin("ChildProcessConnectionImpl.doConnectionSetupLocked");
+ TraceEvent.begin("BaseChildProcessConnection.doConnectionSetupLocked");
assert mServiceConnectComplete && mService != null;
assert mConnectionParams != null;
@@ -460,129 +489,55 @@ public class ChildProcessConnectionImpl implements ChildProcessConnection {
}
mConnectionParams = null;
} finally {
- TraceEvent.end("ChildProcessConnectionImpl.doConnectionSetupLocked");
- }
- }
-
- @Override
- public boolean isInitialBindingBound() {
- synchronized (mLock) {
- return mInitialBinding.isBound();
- }
- }
-
- @Override
- public boolean isStrongBindingBound() {
- synchronized (mLock) {
- return mStrongBinding.isBound();
- }
- }
-
- @Override
- public void removeInitialBinding() {
- synchronized (mLock) {
- assert !mAlwaysInForeground;
- mInitialBinding.unbind();
- }
- }
-
- @Override
- public boolean isOomProtectedOrWasWhenDied() {
- synchronized (mLock) {
- if (mServiceDisconnected) {
- return mWasOomProtected;
- } else {
- return isCurrentlyOomProtected();
- }
- }
- }
-
- private boolean isCurrentlyOomProtected() {
- synchronized (mLock) {
- assert !mServiceDisconnected;
- if (mAlwaysInForeground) return ChildProcessLauncher.isApplicationInForeground();
- return mInitialBinding.isBound() || mStrongBinding.isBound();
+ TraceEvent.end("BaseChildProcessConnection.doConnectionSetupLocked");
}
}
- @Override
- public void dropOomBindings() {
- synchronized (mLock) {
- assert !mAlwaysInForeground;
- mInitialBinding.unbind();
-
- mStrongBindingCount = 0;
- mStrongBinding.unbind();
+ /** Subclasses should implement this method to bind/unbind to the actual service. */
+ protected abstract boolean bind();
+ protected abstract void unbind();
- mModerateBinding.unbind();
- }
+ protected ChildServiceConnection createServiceConnection(int bindFlags) {
+ return new ChildServiceConnectionImpl(bindFlags);
}
- @Override
- public void addStrongBinding() {
- synchronized (mLock) {
- if (mService == null) {
- Log.w(TAG, "The connection is not bound for %d", mPid);
- return;
- }
- if (mStrongBindingCount == 0) {
- mStrongBinding.bind();
- }
- mStrongBindingCount++;
- }
- }
-
- @Override
- public void removeStrongBinding() {
- synchronized (mLock) {
- if (mService == null) {
- Log.w(TAG, "The connection is not bound for %d", mPid);
- return;
- }
- assert mStrongBindingCount > 0;
- mStrongBindingCount--;
- if (mStrongBindingCount == 0) {
- mStrongBinding.unbind();
- }
- }
- }
-
- @Override
- public boolean isModerateBindingBound() {
- synchronized (mLock) {
- return mModerateBinding.isBound();
- }
+ protected boolean shouldBindAsExportedService() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && getCreationParams() != null
+ && getCreationParams().getIsExternalService()
+ && isExportedService(isSandboxed(), getContext(), getServiceName());
}
- @Override
- public void addModerateBinding() {
- synchronized (mLock) {
- if (mService == null) {
- Log.w(TAG, "The connection is not bound for %d", mPid);
- return;
- }
- mModerateBinding.bind();
+ private static boolean isExportedService(
+ boolean inSandbox, Context context, ComponentName serviceName) {
+ // Check for the cached value first. It is assumed that all pooled child services
+ // have identical attributes in the manifest.
+ final int arrayIndex = inSandbox ? 1 : 0;
+ if (sNeedsExtrabindFlags[arrayIndex] != null) {
+ return sNeedsExtrabindFlags[arrayIndex].booleanValue();
}
- }
-
- @Override
- public void removeModerateBinding() {
- synchronized (mLock) {
- if (mService == null) {
- Log.w(TAG, "The connection is not bound for %d", mPid);
- return;
- }
- mModerateBinding.unbind();
+ boolean result = false;
+ try {
+ PackageManager packageManager = context.getPackageManager();
+ ServiceInfo serviceInfo = packageManager.getServiceInfo(serviceName, 0);
+ result = serviceInfo.exported;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Could not retrieve info about service %s", serviceName, e);
}
+ sNeedsExtrabindFlags[arrayIndex] = Boolean.valueOf(result);
+ return result;
}
@VisibleForTesting
public void crashServiceForTesting() throws RemoteException {
- mService.crashIntentionallyForTesting();
+ synchronized (mLock) {
+ mService.crashIntentionallyForTesting();
+ }
}
@VisibleForTesting
public boolean isConnected() {
- return mService != null;
+ synchronized (mLock) {
+ return mService != null;
+ }
}
}
« no previous file with comments | « content/public/android/BUILD.gn ('k') | content/public/android/java/src/org/chromium/content/browser/BindingManager.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698