| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
| 6 | 6 |
| 7 import android.content.ComponentName; | 7 import android.content.ComponentName; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.Intent; | 9 import android.content.Intent; |
| 10 import android.content.ServiceConnection; | 10 import android.content.ServiceConnection; |
| 11 import android.os.AsyncTask; | 11 import android.os.AsyncTask; |
| 12 import android.os.Bundle; | 12 import android.os.Bundle; |
| 13 import android.os.Handler; | 13 import android.os.Handler; |
| 14 import android.os.IBinder; | 14 import android.os.IBinder; |
| 15 import android.os.Looper; | 15 import android.os.Looper; |
| 16 import android.os.ParcelFileDescriptor; | 16 import android.os.ParcelFileDescriptor; |
| 17 import android.util.Log; | 17 import android.util.Log; |
| 18 | 18 |
| 19 import java.io.IOException; |
| 19 import java.util.concurrent.atomic.AtomicBoolean; | 20 import java.util.concurrent.atomic.AtomicBoolean; |
| 20 | 21 |
| 21 import org.chromium.base.CalledByNative; | 22 import org.chromium.base.CalledByNative; |
| 22 import org.chromium.content.app.SandboxedProcessService; | 23 import org.chromium.base.ThreadUtils; |
| 23 import org.chromium.content.common.CommandLine; | 24 import org.chromium.content.common.CommandLine; |
| 24 import org.chromium.content.common.ISandboxedProcessCallback; | 25 import org.chromium.content.common.ISandboxedProcessCallback; |
| 25 import org.chromium.content.common.ISandboxedProcessService; | 26 import org.chromium.content.common.ISandboxedProcessService; |
| 26 import org.chromium.content.common.TraceEvent; | 27 import org.chromium.content.common.TraceEvent; |
| 27 | 28 |
| 28 public class SandboxedProcessConnection { | 29 public class SandboxedProcessConnection implements ServiceConnection { |
| 29 interface DeathCallback { | 30 interface DeathCallback { |
| 30 void onSandboxedProcessDied(int pid); | 31 void onSandboxedProcessDied(int pid); |
| 31 } | 32 } |
| 32 | 33 |
| 33 // Names of items placed in the bind intent or connection bundle. | 34 // Names of items placed in the bind intent or connection bundle. |
| 34 public static final String EXTRA_COMMAND_LINE = | 35 public static final String EXTRA_COMMAND_LINE = |
| 35 "com.google.android.apps.chrome.extra.sandbox_command_line"; | 36 "com.google.android.apps.chrome.extra.sandbox_command_line"; |
| 37 public static final String EXTRA_NATIVE_LIBRARY_NAME = |
| 38 "com.google.android.apps.chrome.extra.sandbox_native_library_name"; |
| 36 // Note the FD may only be passed in the connection bundle. | 39 // Note the FD may only be passed in the connection bundle. |
| 37 public static final String EXTRA_IPC_FD = "com.google.android.apps.chrome.ex
tra.sandbox_ipcFd"; | 40 public static final String EXTRA_IPC_FD = "com.google.android.apps.chrome.ex
tra.sandbox_ipcFd"; |
| 38 public static final String EXTRA_CRASH_FD = | 41 public static final String EXTRA_FILES_PREFIX = |
| 39 "com.google.android.apps.chrome.extra.sandbox_crashFd"; | 42 "com.google.android.apps.chrome.extra.sandbox_extraFile_"; |
| 40 public static final String EXTRA_CHROME_PAK_FD = | 43 public static final String EXTRA_FILES_ID_SUFFIX = "_id"; |
| 41 "com.google.android.apps.chrome.extra.sandbox_chromePakFd"; | 44 public static final String EXTRA_FILES_FD_SUFFIX = "_fd"; |
| 42 public static final String EXTRA_LOCALE_PAK_FD = | |
| 43 "com.google.android.apps.chrome.extra.sandbox_localePakFd"; | |
| 44 | 45 |
| 45 private final Context mContext; | 46 private final Context mContext; |
| 46 private final int mServiceNumber; | 47 private final int mServiceNumber; |
| 47 private final SandboxedProcessConnection.DeathCallback mDeathCallback; | 48 private final SandboxedProcessConnection.DeathCallback mDeathCallback; |
| 48 | 49 |
| 49 // Synchronization: While most internal flow occurs on the UI thread, the pu
blic API | 50 // Synchronization: While most internal flow occurs on the UI thread, the pu
blic API |
| 50 // (specifically bind and unbind) may be called from any thread, hence all e
ntry point methods | 51 // (specifically bind and unbind) may be called from any thread, hence all e
ntry point methods |
| 51 // into the class are synchronized on the SandboxedProcessConnection instanc
e to protect access | 52 // into the class are synchronized on the SandboxedProcessConnection instanc
e to protect access |
| 52 // to these members. But see also the TODO where AsyncBoundServiceConnection
is created. | 53 // to these members. But see also the TODO where AsyncBoundServiceConnection
is created. |
| 53 private ISandboxedProcessService mService = null; | 54 private ISandboxedProcessService mService = null; |
| 54 private boolean mServiceConnectComplete = false; | 55 private boolean mServiceConnectComplete = false; |
| 55 private int mPID = 0; // Process ID of the corresponding sandboxed process. | 56 private int mPID = 0; // Process ID of the corresponding sandboxed process. |
| 56 private HighPriorityConnection mHighPriorityConnection = null; | 57 private HighPriorityConnection mHighPriorityConnection = null; |
| 57 private int mHighPriorityConnectionCount = 0; | 58 private int mHighPriorityConnectionCount = 0; |
| 58 | 59 |
| 59 private static final String TAG = "SandboxedProcessConnection"; | 60 private static final String TAG = "SandboxedProcessConnection"; |
| 60 | 61 |
| 61 private static class ConnectionParams { | 62 private static class ConnectionParams { |
| 62 final String[] mCommandLine; | 63 final String[] mCommandLine; |
| 63 final int mIpcFd; | 64 final int mIpcFd; |
| 64 final int mCrashFd; | 65 final int[] mExtraFileIdsAndFds; |
| 65 final ISandboxedProcessCallback mCallback; | 66 final ISandboxedProcessCallback mCallback; |
| 66 final Runnable mOnConnectionCallback; | 67 final Runnable mOnConnectionCallback; |
| 67 | 68 |
| 68 ConnectionParams( | 69 ConnectionParams( |
| 69 String[] commandLine, | 70 String[] commandLine, |
| 70 int ipcFd, | 71 int ipcFd, |
| 71 int crashFd, | 72 int[] idsAndFds, |
| 72 ISandboxedProcessCallback callback, | 73 ISandboxedProcessCallback callback, |
| 73 Runnable onConnectionCallback) { | 74 Runnable onConnectionCallback) { |
| 74 mCommandLine = commandLine; | 75 mCommandLine = commandLine; |
| 75 mIpcFd = ipcFd; | 76 mIpcFd = ipcFd; |
| 76 mCrashFd = crashFd; | 77 mExtraFileIdsAndFds = idsAndFds; |
| 77 mCallback = callback; | 78 mCallback = callback; |
| 78 mOnConnectionCallback = onConnectionCallback; | 79 mOnConnectionCallback = onConnectionCallback; |
| 79 } | 80 } |
| 80 }; | |
| 81 | |
| 82 // Implement the ServiceConnection as an inner class, so it can stem the ser
vice | |
| 83 // callbacks when cancelled or unbound. | |
| 84 class AsyncBoundServiceConnection extends AsyncTask<Intent, Void, Boolean> | |
| 85 implements ServiceConnection { | |
| 86 private boolean mIsDestroyed = false; | |
| 87 private AtomicBoolean mIsBound = new AtomicBoolean(false); | |
| 88 | |
| 89 // AsyncTask | |
| 90 @Override | |
| 91 protected Boolean doInBackground(Intent... intents) { | |
| 92 boolean isBound = mContext.bindService(intents[0], this, Context.BIN
D_AUTO_CREATE); | |
| 93 mIsBound.set(isBound); | |
| 94 return isBound; | |
| 95 } | |
| 96 | |
| 97 @Override | |
| 98 protected void onPostExecute(Boolean boundOK) { | |
| 99 synchronized (SandboxedProcessConnection.this) { | |
| 100 if (!boundOK && !mIsDestroyed) { | |
| 101 SandboxedProcessConnection.this.onBindFailed(); | |
| 102 } | |
| 103 // else: bind will complete asynchronously with a callback to on
ServiceConnected(). | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 @Override | |
| 108 protected void onCancelled(Boolean boundOK) { | |
| 109 // According to {@link AsyncTask#onCancelled(Object)}, the Object ca
n be null. | |
| 110 if (boundOK != null && boundOK) { | |
| 111 unBindIfAble(); | |
| 112 } | |
| 113 } | |
| 114 | |
| 115 /** | |
| 116 * Unbinds this connection if it hasn't already been unbound. There's a
guard to check that | |
| 117 * we haven't already been unbound because the Browser process cancellin
g a connection can | |
| 118 * race with something else (Android?) cancelling the connection. | |
| 119 */ | |
| 120 private void unBindIfAble() { | |
| 121 if (mIsBound.getAndSet(false)) { | |
| 122 mContext.unbindService(this); | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 // ServiceConnection | |
| 127 @Override | |
| 128 public void onServiceConnected(ComponentName name, IBinder service) { | |
| 129 synchronized (SandboxedProcessConnection.this) { | |
| 130 if (!mIsDestroyed) { | |
| 131 SandboxedProcessConnection.this.onServiceConnected(name, ser
vice); | |
| 132 } | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 @Override | |
| 137 public void onServiceDisconnected(ComponentName name) { | |
| 138 synchronized (SandboxedProcessConnection.this) { | |
| 139 if (!mIsDestroyed) { | |
| 140 SandboxedProcessConnection.this.onServiceDisconnected(name); | |
| 141 } | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 public void destroy() { | |
| 146 assert Thread.holdsLock(SandboxedProcessConnection.this); | |
| 147 if (!cancel(false)) { | |
| 148 unBindIfAble(); | |
| 149 } | |
| 150 mIsDestroyed = true; | |
| 151 } | |
| 152 } | 81 } |
| 153 | 82 |
| 154 // This is only valid while the connection is being established. | 83 // This is only valid while the connection is being established. |
| 155 private ConnectionParams mConnectionParams; | 84 private ConnectionParams mConnectionParams; |
| 156 private AsyncBoundServiceConnection mServiceConnection; | 85 private boolean mIsBound; |
| 157 | 86 |
| 158 SandboxedProcessConnection(Context context, int number, | 87 SandboxedProcessConnection(Context context, int number, |
| 159 SandboxedProcessConnection.DeathCallback deathCallback) { | 88 SandboxedProcessConnection.DeathCallback deathCallback) { |
| 160 mContext = context; | 89 mContext = context; |
| 161 mServiceNumber = number; | 90 mServiceNumber = number; |
| 162 mDeathCallback = deathCallback; | 91 mDeathCallback = deathCallback; |
| 163 } | 92 } |
| 164 | 93 |
| 165 int getServiceNumber() { | 94 int getServiceNumber() { |
| 166 return mServiceNumber; | 95 return mServiceNumber; |
| 167 } | 96 } |
| 168 | 97 |
| 169 synchronized ISandboxedProcessService getService() { | 98 synchronized ISandboxedProcessService getService() { |
| 170 return mService; | 99 return mService; |
| 171 } | 100 } |
| 172 | 101 |
| 173 private Intent createServiceBindIntent() { | 102 private Intent createServiceBindIntent() { |
| 174 Intent intent = new Intent(); | 103 Intent intent = new Intent(); |
| 175 String n = SandboxedProcessService.class.getName(); | 104 String n = org.chromium.content.app.SandboxedProcessService.class.getNam
e(); |
| 176 intent.setClassName(mContext, n + mServiceNumber); | 105 intent.setClassName(mContext, n + mServiceNumber); |
| 177 intent.setPackage(mContext.getPackageName()); | 106 intent.setPackage(mContext.getPackageName()); |
| 178 return intent; | 107 return intent; |
| 179 } | 108 } |
| 180 | 109 |
| 181 /** | 110 /** |
| 182 * Bind to an ISandboxedProcessService. This must be followed by a call to s
etupConnection() | 111 * Bind to an ISandboxedProcessService. This must be followed by a call to s
etupConnection() |
| 183 * to setup the connection parameters. (These methods are separated to allow
the client | 112 * to setup the connection parameters. (These methods are separated to allow
the client |
| 184 * to pass whatever parameters they have available here, and complete the re
mainder | 113 * to pass whatever parameters they have available here, and complete the re
mainder |
| 185 * later while reducing the connection setup latency). | 114 * later while reducing the connection setup latency). |
| 186 * | 115 * @param nativeLibraryName The name of the shared native library to be load
ed for the |
| 116 * sandboxed process. |
| 187 * @param commandLine (Optional) Command line for the sandboxed process. If
omitted, then | 117 * @param commandLine (Optional) Command line for the sandboxed process. If
omitted, then |
| 188 * the command line parameters must instead be passed to setupConnection(). | 118 * the command line parameters must instead be passed to
setupConnection(). |
| 189 */ | 119 */ |
| 190 synchronized void bind(String[] commandLine) { | 120 synchronized void bind(String nativeLibraryName, String[] commandLine) { |
| 191 TraceEvent.begin(); | 121 TraceEvent.begin(); |
| 122 assert !ThreadUtils.runningOnUiThread(); |
| 123 |
| 192 final Intent intent = createServiceBindIntent(); | 124 final Intent intent = createServiceBindIntent(); |
| 193 | 125 |
| 126 intent.putExtra(EXTRA_NATIVE_LIBRARY_NAME, nativeLibraryName); |
| 194 if (commandLine != null) { | 127 if (commandLine != null) { |
| 195 intent.putExtra(EXTRA_COMMAND_LINE, commandLine); | 128 intent.putExtra(EXTRA_COMMAND_LINE, commandLine); |
| 196 } | 129 } |
| 197 // TODO(joth): By the docs, AsyncTasks should only be created on the UI
thread, but | 130 |
| 198 // bind() currently 'may' be called on any thread. In practice it's only
ever called | 131 mIsBound = mContext.bindService(intent, this, Context.BIND_AUTO_CREATE); |
| 199 // from UI, but it's not guaranteed. See http://b/5694925. | 132 if (!mIsBound) { |
| 200 Looper mainLooper = Looper.getMainLooper(); | 133 onBindFailed(); |
| 201 if (Looper.myLooper() == mainLooper) { | |
| 202 mServiceConnection = new AsyncBoundServiceConnection(); | |
| 203 // On completion this will call back to onServiceConnected(). | |
| 204 mServiceConnection.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
intent); | |
| 205 } else { | |
| 206 // TODO(jcivelli): http://b/5694925 we only have to post to the UI t
hread because we use | |
| 207 // an AsyncTask and it requires it. Replace that AsyncTask by runnin
g our own thread and | |
| 208 // change this so we run directly from the current thread. | |
| 209 new Handler(mainLooper).postAtFrontOfQueue(new Runnable() { | |
| 210 public void run() { | |
| 211 mServiceConnection = new AsyncBoundServiceConnection
(); | |
| 212 // On completion this will call back to onServiceCon
nected(). | |
| 213 mServiceConnection.executeOnExecutor(AsyncTask.THREA
D_POOL_EXECUTOR, | |
| 214 intent); | |
| 215 } | |
| 216 }); | |
| 217 } | 134 } |
| 218 TraceEvent.end(); | 135 TraceEvent.end(); |
| 219 } | 136 } |
| 220 | 137 |
| 221 /** Setup a connection previous bound via a call to bind(). | 138 /** Setup a connection previous bound via a call to bind(). |
| 222 * | 139 * |
| 223 * This establishes the parameters that were not already supplied in bind. | 140 * This establishes the parameters that were not already supplied in bind. |
| 224 * @param commandLine (Optional) will be ignored if the command line was alr
eady sent in bind() | 141 * @param commandLine (Optional) will be ignored if the command line was alr
eady sent in bind() |
| 225 * @param ipcFd The file descriptor that will be used by the sandbox process
for IPC. | 142 * @param ipcFd The file descriptor that will be used by the sandbox process
for IPC. |
| 226 * @param crashFd (Optional) file descriptor that will be used for crash dum
ps. | 143 * @param fileToRegisterIdFds (Optional) a list of pair of IDs and FDs that
should be |
| 144 * registered |
| 227 * @param callback Used for status updates regarding this process connection
. | 145 * @param callback Used for status updates regarding this process connection
. |
| 228 * @param onConnectionCallback will be run when the connection is setup and
ready to use. | 146 * @param onConnectionCallback will be run when the connection is setup and
ready to use. |
| 229 */ | 147 */ |
| 230 synchronized void setupConnection( | 148 synchronized void setupConnection( |
| 231 String[] commandLine, | 149 String[] commandLine, |
| 232 int ipcFd, | 150 int ipcFd, |
| 233 int crashFd, | 151 int[] fileToRegisterIdFds, |
| 234 ISandboxedProcessCallback callback, | 152 ISandboxedProcessCallback callback, |
| 235 Runnable onConnectionCallback) { | 153 Runnable onConnectionCallback) { |
| 236 TraceEvent.begin(); | 154 TraceEvent.begin(); |
| 237 assert mConnectionParams == null; | 155 assert mConnectionParams == null; |
| 238 mConnectionParams = new ConnectionParams(commandLine, ipcFd, crashFd, ca
llback, | 156 mConnectionParams = new ConnectionParams(commandLine, ipcFd, fileToRegis
terIdFds, callback, |
| 239 onConnectionCallback); | 157 onConnectionCallback); |
| 240 if (mServiceConnectComplete) { | 158 if (mServiceConnectComplete) { |
| 241 doConnectionSetup(); | 159 doConnectionSetup(); |
| 242 } | 160 } |
| 243 TraceEvent.end(); | 161 TraceEvent.end(); |
| 244 } | 162 } |
| 245 | 163 |
| 246 /** | 164 /** |
| 247 * Unbind the ISandboxedProcessService. It is safe to call this multiple tim
es. | 165 * Unbind the ISandboxedProcessService. It is safe to call this multiple tim
es. |
| 248 */ | 166 */ |
| 249 synchronized void unbind() { | 167 synchronized void unbind() { |
| 250 if (mServiceConnection != null) { | 168 if (mIsBound) { |
| 251 mServiceConnection.destroy(); | 169 mContext.unbindService(this); |
| 252 mServiceConnection = null; | 170 mIsBound = false; |
| 253 } | 171 } |
| 254 if (mService != null) { | 172 if (mService != null) { |
| 255 if (mHighPriorityConnection != null) { | 173 if (mHighPriorityConnection != null) { |
| 256 unbindHighPriority(true); | 174 unbindHighPriority(true); |
| 257 } | 175 } |
| 258 mService = null; | 176 mService = null; |
| 259 mPID = 0; | 177 mPID = 0; |
| 260 } | 178 } |
| 261 mConnectionParams = null; | 179 mConnectionParams = null; |
| 262 mServiceConnectComplete = false; | 180 mServiceConnectComplete = false; |
| 263 } | 181 } |
| 264 | 182 |
| 265 // Called on the main thread to notify that the service is connected. | 183 // Called on the main thread to notify that the service is connected. |
| 266 private void onServiceConnected(ComponentName className, IBinder service) { | 184 @Override |
| 267 assert Thread.holdsLock(this); | 185 public void onServiceConnected(ComponentName className, IBinder service) { |
| 268 TraceEvent.begin(); | 186 TraceEvent.begin(); |
| 269 mServiceConnectComplete = true; | 187 mServiceConnectComplete = true; |
| 270 mService = ISandboxedProcessService.Stub.asInterface(service); | 188 mService = ISandboxedProcessService.Stub.asInterface(service); |
| 271 if (mConnectionParams != null) { | 189 if (mConnectionParams != null) { |
| 272 doConnectionSetup(); | 190 doConnectionSetup(); |
| 273 } | 191 } |
| 274 TraceEvent.end(); | 192 TraceEvent.end(); |
| 275 } | 193 } |
| 276 | 194 |
| 277 // Called on the main thread to notify that the bindService() call failed (r
eturned false). | 195 // Called on the main thread to notify that the bindService() call failed (r
eturned false). |
| 278 private void onBindFailed() { | 196 private void onBindFailed() { |
| 279 assert Thread.holdsLock(this); | |
| 280 mServiceConnectComplete = true; | 197 mServiceConnectComplete = true; |
| 281 if (mConnectionParams != null) { | 198 if (mConnectionParams != null) { |
| 282 doConnectionSetup(); | 199 doConnectionSetup(); |
| 283 } | 200 } |
| 284 } | 201 } |
| 285 | 202 |
| 286 /** | 203 /** |
| 287 * Called when the connection parameters have been set, and a connection has
been established | 204 * Called when the connection parameters have been set, and a connection has
been established |
| 288 * (as signaled by onServiceConnected), or if the connection failed (mServic
e will be false). | 205 * (as signaled by onServiceConnected), or if the connection failed (mServic
e will be false). |
| 289 */ | 206 */ |
| 290 private void doConnectionSetup() { | 207 private void doConnectionSetup() { |
| 291 TraceEvent.begin(); | 208 TraceEvent.begin(); |
| 292 assert mServiceConnectComplete && mConnectionParams != null; | 209 assert mServiceConnectComplete && mConnectionParams != null; |
| 293 // Capture the callback before it is potentially nulled in unbind(). | 210 // Capture the callback before it is potentially nulled in unbind(). |
| 294 Runnable onConnectionCallback = | 211 Runnable onConnectionCallback = |
| 295 mConnectionParams != null ? mConnectionParams.mOnConnectionCallback
: null; | 212 mConnectionParams != null ? mConnectionParams.mOnConnectionCallback
: null; |
| 296 if (onConnectionCallback == null) { | 213 if (onConnectionCallback == null) { |
| 297 unbind(); | 214 unbind(); |
| 298 } else if (mService != null) { | 215 } else if (mService != null) { |
| 216 ParcelFileDescriptor ipcFdParcel; |
| 299 try { | 217 try { |
| 300 ParcelFileDescriptor ipcFdParcel = | 218 ipcFdParcel = ParcelFileDescriptor.fromFd(mConnectionParams.mIpc
Fd); |
| 301 ParcelFileDescriptor.fromFd(mConnectionParams.mIpcFd); | 219 } catch(IOException e) { |
| 302 Bundle bundle = new Bundle(); | 220 Log.e(TAG, "Invalid IPC FD, aborting connection.", e); |
| 303 bundle.putStringArray(EXTRA_COMMAND_LINE, mConnectionParams.mCom
mandLine); | 221 return; |
| 304 bundle.putParcelable(EXTRA_IPC_FD, ipcFdParcel); | 222 } |
| 223 Bundle bundle = new Bundle(); |
| 224 bundle.putStringArray(EXTRA_COMMAND_LINE, mConnectionParams.mCommand
Line); |
| 225 bundle.putParcelable(EXTRA_IPC_FD, ipcFdParcel); |
| 305 | 226 |
| 227 int[] idsAndFds = mConnectionParams.mExtraFileIdsAndFds; |
| 228 assert idsAndFds.length % 2 == 0; |
| 229 int pairLength = idsAndFds.length / 2; |
| 230 for (int i = 0; i < pairLength; i++) { |
| 231 String idName = EXTRA_FILES_PREFIX + i + EXTRA_FILES_ID_SUFFIX; |
| 232 String fdName = EXTRA_FILES_PREFIX + i + EXTRA_FILES_FD_SUFFIX; |
| 233 ParcelFileDescriptor parcelFile; |
| 306 try { | 234 try { |
| 307 ParcelFileDescriptor crashFdParcel = | 235 parcelFile = ParcelFileDescriptor.fromFd(idsAndFds[(2 * i) +
1]); |
| 308 ParcelFileDescriptor.fromFd(mConnectionParams.mCrashFd); | 236 bundle.putParcelable(fdName, parcelFile); |
| 309 bundle.putParcelable(EXTRA_CRASH_FD, crashFdParcel); | 237 bundle.putInt(idName, idsAndFds[2 * i]); |
| 310 // We will let the GC close the crash ParcelFileDescriptor. | 238 } catch (IOException e) { |
| 311 } catch (java.io.IOException e) { | 239 Log.e(TAG, "Invalid extra file FD: id=" + idsAndFds[ 2 * i]
+ " fd=" |
| 312 Log.w(TAG, "Invalid crash Fd. Native crash reporting will be
disabled."); | 240 + idsAndFds[(2 * i) + 1]); |
| 313 } | 241 } |
| 314 | 242 } |
| 243 try { |
| 315 mPID = mService.setupConnection(bundle, mConnectionParams.mCallb
ack); | 244 mPID = mService.setupConnection(bundle, mConnectionParams.mCallb
ack); |
| 316 ipcFdParcel.close(); // We proactivley close now rather than wa
it for GC & | 245 } catch (android.os.RemoteException re) { |
| 317 // finalizer. | 246 Log.e(TAG, "Failed to setup connection.", re); |
| 318 } catch(java.io.IOException e) { | 247 } |
| 319 Log.w(TAG, "Invalid ipc FD."); | 248 try { |
| 320 } catch(android.os.RemoteException e) { | 249 // We proactivley close now rather than wait for GC & finalizer. |
| 321 Log.w(TAG, "Exception when trying to call service method: " | 250 ipcFdParcel.close(); |
| 322 + e); | 251 } catch (IOException ioe) { |
| 252 Log.w(TAG, "Failed to close IPC FD.", ioe); |
| 323 } | 253 } |
| 324 } | 254 } |
| 325 mConnectionParams = null; | 255 mConnectionParams = null; |
| 326 if (onConnectionCallback != null) { | 256 if (onConnectionCallback != null) { |
| 327 onConnectionCallback.run(); | 257 onConnectionCallback.run(); |
| 328 } | 258 } |
| 329 TraceEvent.end(); | 259 TraceEvent.end(); |
| 330 } | 260 } |
| 331 | 261 |
| 332 // Called on the main thread to notify that the sandboxed service did not di
sconnect gracefully. | 262 // Called on the main thread to notify that the sandboxed service did not di
sconnect gracefully. |
| 333 private void onServiceDisconnected(ComponentName className) { | 263 @Override |
| 334 assert Thread.holdsLock(this); | 264 public void onServiceDisconnected(ComponentName className) { |
| 335 int pid = mPID; // Stash pid & connection callback since unbind() will
clear them. | 265 int pid = mPID; // Stash pid & connection callback since unbind() will
clear them. |
| 336 Runnable onConnectionCallback = | 266 Runnable onConnectionCallback = |
| 337 mConnectionParams != null ? mConnectionParams.mOnConnectionCallback
: null; | 267 mConnectionParams != null ? mConnectionParams.mOnConnectionCallback
: null; |
| 338 Log.w(TAG, "onServiceDisconnected (crash?): pid=" + pid); | 268 Log.w(TAG, "onServiceDisconnected (crash?): pid=" + pid); |
| 339 unbind(); // We don't want to auto-restart on crash. Let the browser do
that. | 269 unbind(); // We don't want to auto-restart on crash. Let the browser do
that. |
| 340 if (pid != 0) { | 270 if (pid != 0) { |
| 341 mDeathCallback.onSandboxedProcessDied(pid); | 271 mDeathCallback.onSandboxedProcessDied(pid); |
| 342 } | 272 } |
| 343 if (onConnectionCallback != null) { | 273 if (onConnectionCallback != null) { |
| 344 onConnectionCallback.run(); | 274 onConnectionCallback.run(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 } | 333 } |
| 404 } | 334 } |
| 405 | 335 |
| 406 /** | 336 /** |
| 407 * @return The connection PID, or 0 if not yet connected. | 337 * @return The connection PID, or 0 if not yet connected. |
| 408 */ | 338 */ |
| 409 synchronized public int getPid() { | 339 synchronized public int getPid() { |
| 410 return mPID; | 340 return mPID; |
| 411 } | 341 } |
| 412 } | 342 } |
| OLD | NEW |