OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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.content.pm.PackageManager; | 11 import android.content.pm.PackageManager; |
12 import android.content.pm.ServiceInfo; | 12 import android.content.pm.ServiceInfo; |
13 import android.os.Build; | 13 import android.os.Build; |
14 import android.os.Bundle; | 14 import android.os.Bundle; |
15 import android.os.IBinder; | 15 import android.os.IBinder; |
16 import android.os.RemoteException; | 16 import android.os.RemoteException; |
17 | 17 |
18 import org.chromium.base.Log; | 18 import org.chromium.base.Log; |
19 import org.chromium.base.TraceEvent; | 19 import org.chromium.base.TraceEvent; |
20 import org.chromium.base.VisibleForTesting; | 20 import org.chromium.base.VisibleForTesting; |
21 import org.chromium.base.process_launcher.ChildProcessCreationParams; | 21 import org.chromium.base.process_launcher.ChildProcessCreationParams; |
22 import org.chromium.base.process_launcher.FileDescriptorInfo; | 22 import org.chromium.base.process_launcher.FileDescriptorInfo; |
23 import org.chromium.base.process_launcher.ICallbackInt; | 23 import org.chromium.base.process_launcher.ICallbackInt; |
24 import org.chromium.base.process_launcher.IChildProcessService; | 24 import org.chromium.base.process_launcher.IChildProcessService; |
25 | 25 |
26 import java.io.IOException; | 26 import java.io.IOException; |
27 | 27 |
28 import javax.annotation.Nullable; | 28 import javax.annotation.Nullable; |
29 import javax.annotation.concurrent.GuardedBy; | |
30 | 29 |
31 /** | 30 /** |
32 * Manages a connection between the browser activity and a child service. | 31 * Manages a connection between the browser activity and a child service. |
33 */ | 32 */ |
34 public abstract class BaseChildProcessConnection { | 33 public abstract class BaseChildProcessConnection { |
35 private static final String TAG = "BaseChildProcessConn"; | 34 private static final String TAG = "BaseChildProcessConn"; |
36 | 35 |
37 /** | 36 /** |
38 * Used to notify the consumer about disconnection of the service. This call
back is provided | 37 * Used to notify the consumer about disconnection of the service. This call
back is provided |
39 * earlier than ConnectionCallbacks below, as a child process might die befo
re the connection is | 38 * earlier than ConnectionCallbacks below, as a child process might die befo
re the connection is |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 final IBinder mCallback; | 180 final IBinder mCallback; |
182 | 181 |
183 ConnectionParams( | 182 ConnectionParams( |
184 String[] commandLine, FileDescriptorInfo[] filesToBeMapped, IBin
der callback) { | 183 String[] commandLine, FileDescriptorInfo[] filesToBeMapped, IBin
der callback) { |
185 mCommandLine = commandLine; | 184 mCommandLine = commandLine; |
186 mFilesToBeMapped = filesToBeMapped; | 185 mFilesToBeMapped = filesToBeMapped; |
187 mCallback = callback; | 186 mCallback = callback; |
188 } | 187 } |
189 } | 188 } |
190 | 189 |
191 // Synchronization: While most internal flow occurs on the UI thread, the pu
blic API | |
192 // (specifically start and stop) may be called from any thread, hence all en
try point methods | |
193 // into the class are synchronized on the lock to protect access to these me
mbers. | |
194 // TODO(jcivelli): crbug.com/714657 remove this lock. | |
195 private final Object mLock = new Object(); | |
196 | |
197 // This is set in start() and is used in onServiceConnected(). | 190 // This is set in start() and is used in onServiceConnected(). |
198 @GuardedBy("mLock") | |
199 private StartCallback mStartCallback; | 191 private StartCallback mStartCallback; |
200 | 192 |
201 // This is set in setupConnection() and is later used in doConnectionSetupLo
cked(), after which | 193 // This is set in setupConnection() and is later used in doConnectionSetupLo
cked(), after which |
202 // the variable is cleared. Therefore this is only valid while the connectio
n is being set up. | 194 // the variable is cleared. Therefore this is only valid while the connectio
n is being set up. |
203 @GuardedBy("mLock") | |
204 private ConnectionParams mConnectionParams; | 195 private ConnectionParams mConnectionParams; |
205 | 196 |
206 // Callback provided in setupConnection() that will communicate the result t
o the caller. This | 197 // Callback provided in setupConnection() that will communicate the result t
o the caller. This |
207 // has to be called exactly once after setupConnection(), even if setup fail
s, so that the | 198 // has to be called exactly once after setupConnection(), even if setup fail
s, so that the |
208 // caller can free up resources associated with the setup attempt. This is s
et to null after the | 199 // caller can free up resources associated with the setup attempt. This is s
et to null after the |
209 // call. | 200 // call. |
210 @GuardedBy("mLock") | |
211 private ConnectionCallback mConnectionCallback; | 201 private ConnectionCallback mConnectionCallback; |
212 | 202 |
213 @GuardedBy("mLock") | |
214 private IChildProcessService mService; | 203 private IChildProcessService mService; |
215 | 204 |
216 // Set to true when the service connection callback runs. This differs from | 205 // Set to true when the service connection callback runs. This differs from |
217 // mServiceConnectComplete, which tracks that the connection completed succe
ssfully. | 206 // mServiceConnectComplete, which tracks that the connection completed succe
ssfully. |
218 @GuardedBy("mLock") | |
219 private boolean mDidOnServiceConnected; | 207 private boolean mDidOnServiceConnected; |
220 | 208 |
221 // Set to true when the service connected successfully. | 209 // Set to true when the service connected successfully. |
222 @GuardedBy("mLock") | |
223 private boolean mServiceConnectComplete; | 210 private boolean mServiceConnectComplete; |
224 | 211 |
225 // Set to true when the service disconnects, as opposed to being properly cl
osed. This happens | 212 // Set to true when the service disconnects, as opposed to being properly cl
osed. This happens |
226 // when the process crashes or gets killed by the system out-of-memory kille
r. | 213 // when the process crashes or gets killed by the system out-of-memory kille
r. |
227 @GuardedBy("mLock") | |
228 private boolean mServiceDisconnected; | 214 private boolean mServiceDisconnected; |
229 | 215 |
230 // Process ID of the corresponding child process. | 216 // Process ID of the corresponding child process. |
231 @GuardedBy("mLock") | |
232 private int mPid; | 217 private int mPid; |
233 | 218 |
234 protected BaseChildProcessConnection(Context context, int number, boolean sa
ndboxed, | 219 protected BaseChildProcessConnection(Context context, int number, boolean sa
ndboxed, |
235 DeathCallback deathCallback, String serviceClassName, | 220 DeathCallback deathCallback, String serviceClassName, |
236 Bundle childProcessCommonParameters, ChildProcessCreationParams crea
tionParams) { | 221 Bundle childProcessCommonParameters, ChildProcessCreationParams crea
tionParams) { |
| 222 assert LauncherThread.runningOnLauncherThread(); |
237 mContext = context; | 223 mContext = context; |
238 mServiceNumber = number; | 224 mServiceNumber = number; |
239 mSandboxed = sandboxed; | 225 mSandboxed = sandboxed; |
240 mDeathCallback = deathCallback; | 226 mDeathCallback = deathCallback; |
241 String packageName = | 227 String packageName = |
242 creationParams != null ? creationParams.getPackageName() : conte
xt.getPackageName(); | 228 creationParams != null ? creationParams.getPackageName() : conte
xt.getPackageName(); |
243 mServiceName = new ComponentName(packageName, serviceClassName + mServic
eNumber); | 229 mServiceName = new ComponentName(packageName, serviceClassName + mServic
eNumber); |
244 mChildProcessCommonParameters = childProcessCommonParameters; | 230 mChildProcessCommonParameters = childProcessCommonParameters; |
245 mCreationParams = creationParams; | 231 mCreationParams = creationParams; |
246 } | 232 } |
247 | 233 |
248 public final Context getContext() { | 234 public final Context getContext() { |
| 235 assert LauncherThread.runningOnLauncherThread(); |
249 return mContext; | 236 return mContext; |
250 } | 237 } |
251 | 238 |
252 public final int getServiceNumber() { | 239 public final int getServiceNumber() { |
| 240 assert LauncherThread.runningOnLauncherThread(); |
253 return mServiceNumber; | 241 return mServiceNumber; |
254 } | 242 } |
255 | 243 |
256 public final boolean isSandboxed() { | 244 public final boolean isSandboxed() { |
| 245 assert LauncherThread.runningOnLauncherThread(); |
257 return mSandboxed; | 246 return mSandboxed; |
258 } | 247 } |
259 | 248 |
260 public final String getPackageName() { | 249 public final String getPackageName() { |
| 250 assert LauncherThread.runningOnLauncherThread(); |
261 return mCreationParams != null ? mCreationParams.getPackageName() | 251 return mCreationParams != null ? mCreationParams.getPackageName() |
262 : mContext.getPackageName(); | 252 : mContext.getPackageName(); |
263 } | 253 } |
264 | 254 |
265 public final ChildProcessCreationParams getCreationParams() { | 255 public final ChildProcessCreationParams getCreationParams() { |
| 256 assert LauncherThread.runningOnLauncherThread(); |
266 return mCreationParams; | 257 return mCreationParams; |
267 } | 258 } |
268 | 259 |
269 public final IChildProcessService getService() { | 260 public final IChildProcessService getService() { |
270 synchronized (mLock) { | 261 assert LauncherThread.runningOnLauncherThread(); |
271 return mService; | 262 return mService; |
272 } | |
273 } | 263 } |
274 | 264 |
275 public final ComponentName getServiceName() { | 265 public final ComponentName getServiceName() { |
| 266 assert LauncherThread.runningOnLauncherThread(); |
276 return mServiceName; | 267 return mServiceName; |
277 } | 268 } |
278 | 269 |
279 /** | 270 /** |
280 * @return the connection pid, or 0 if not yet connected | 271 * @return the connection pid, or 0 if not yet connected |
281 */ | 272 */ |
282 public int getPid() { | 273 public int getPid() { |
283 synchronized (mLock) { | 274 assert LauncherThread.runningOnLauncherThread(); |
284 return mPid; | 275 return mPid; |
285 } | |
286 } | 276 } |
287 | 277 |
288 /** | 278 /** |
289 * Starts a connection to an IChildProcessService. This must be followed by
a call to | 279 * Starts a connection to an IChildProcessService. This must be followed by
a call to |
290 * setupConnection() to setup the connection parameters. start() and setupCo
nnection() are | 280 * setupConnection() to setup the connection parameters. start() and setupCo
nnection() are |
291 * separate to allow to pass whatever parameters are available in start(), a
nd complete the | 281 * separate to allow to pass whatever parameters are available in start(), a
nd complete the |
292 * remainder later while reducing the connection setup latency. | 282 * remainder later while reducing the connection setup latency. |
293 * @param startCallback (optional) callback when the child process starts or
fails to start. | 283 * @param startCallback (optional) callback when the child process starts or
fails to start. |
294 */ | 284 */ |
295 public void start(StartCallback startCallback) { | 285 public void start(StartCallback startCallback) { |
| 286 assert LauncherThread.runningOnLauncherThread(); |
296 try { | 287 try { |
297 TraceEvent.begin("BaseChildProcessConnection.start"); | 288 TraceEvent.begin("BaseChildProcessConnection.start"); |
298 assert LauncherThread.runningOnLauncherThread(); | 289 assert LauncherThread.runningOnLauncherThread(); |
299 synchronized (mLock) { | 290 assert mConnectionParams |
300 assert mConnectionParams | 291 == null |
301 == null | 292 : "setupConnection() called before start() in BaseChildProce
ssConnection."; |
302 : "setupConnection() called before start() in BaseChildP
rocessConnection."; | |
303 | 293 |
304 mStartCallback = startCallback; | 294 mStartCallback = startCallback; |
305 | 295 |
306 if (!bind()) { | 296 if (!bind()) { |
307 Log.e(TAG, "Failed to establish the service connection."); | 297 Log.e(TAG, "Failed to establish the service connection."); |
308 // We have to notify the caller so that they can free-up ass
ociated resources. | 298 // We have to notify the caller so that they can free-up associa
ted resources. |
309 // TODO(ppi): Can we hard-fail here? | 299 // TODO(ppi): Can we hard-fail here? |
310 mDeathCallback.onChildProcessDied(BaseChildProcessConnection
.this); | 300 mDeathCallback.onChildProcessDied(BaseChildProcessConnection.thi
s); |
311 } | |
312 } | 301 } |
313 } finally { | 302 } finally { |
314 TraceEvent.end("BaseChildProcessConnection.start"); | 303 TraceEvent.end("BaseChildProcessConnection.start"); |
315 } | 304 } |
316 } | 305 } |
317 | 306 |
318 /** | 307 /** |
319 * Setups the connection after it was started with start(). | 308 * Setups the connection after it was started with start(). |
320 * @param commandLine (optional) will be ignored if the command line was alr
eady sent in start() | 309 * @param commandLine (optional) will be ignored if the command line was alr
eady sent in start() |
321 * @param filesToBeMapped a list of file descriptors that should be register
ed | 310 * @param filesToBeMapped a list of file descriptors that should be register
ed |
322 * @param callback optional client specified callbacks that the child can us
e to communicate | 311 * @param callback optional client specified callbacks that the child can us
e to communicate |
323 * with the parent process | 312 * with the parent process |
324 * @param connectionCallback will be called exactly once after the connectio
n is set up or the | 313 * @param connectionCallback will be called exactly once after the connectio
n is set up or the |
325 * setup fails | 314 * setup fails |
326 */ | 315 */ |
327 public void setupConnection(String[] commandLine, FileDescriptorInfo[] files
ToBeMapped, | 316 public void setupConnection(String[] commandLine, FileDescriptorInfo[] files
ToBeMapped, |
328 @Nullable IBinder callback, ConnectionCallback connectionCallback) { | 317 @Nullable IBinder callback, ConnectionCallback connectionCallback) { |
329 assert LauncherThread.runningOnLauncherThread(); | 318 assert LauncherThread.runningOnLauncherThread(); |
330 synchronized (mLock) { | 319 assert mConnectionParams == null; |
331 assert mConnectionParams == null; | 320 if (mServiceDisconnected) { |
332 if (mServiceDisconnected) { | 321 Log.w(TAG, "Tried to setup a connection that already disconnected.")
; |
333 Log.w(TAG, "Tried to setup a connection that already disconnecte
d."); | 322 connectionCallback.onConnected(null); |
334 connectionCallback.onConnected(null); | 323 return; |
335 return; | 324 } |
| 325 try { |
| 326 TraceEvent.begin("BaseChildProcessConnection.setupConnection"); |
| 327 mConnectionCallback = connectionCallback; |
| 328 mConnectionParams = new ConnectionParams(commandLine, filesToBeMappe
d, callback); |
| 329 // Run the setup if the service is already connected. If not, |
| 330 // doConnectionSetupLocked() will be called from onServiceConnected(
). |
| 331 if (mServiceConnectComplete) { |
| 332 doConnectionSetupLocked(); |
336 } | 333 } |
337 try { | 334 } finally { |
338 TraceEvent.begin("BaseChildProcessConnection.setupConnection"); | 335 TraceEvent.end("BaseChildProcessConnection.setupConnection"); |
339 mConnectionCallback = connectionCallback; | |
340 mConnectionParams = new ConnectionParams(commandLine, filesToBeM
apped, callback); | |
341 // Run the setup if the service is already connected. If not, | |
342 // doConnectionSetupLocked() will be called from onServiceConnec
ted(). | |
343 if (mServiceConnectComplete) { | |
344 doConnectionSetupLocked(); | |
345 } | |
346 } finally { | |
347 TraceEvent.end("BaseChildProcessConnection.setupConnection"); | |
348 } | |
349 } | 336 } |
350 } | 337 } |
351 | 338 |
352 /** | 339 /** |
353 * Terminates the connection to IChildProcessService, closing all bindings.
It is safe to call | 340 * Terminates the connection to IChildProcessService, closing all bindings.
It is safe to call |
354 * this multiple times. | 341 * this multiple times. |
355 */ | 342 */ |
356 public void stop() { | 343 public void stop() { |
357 synchronized (mLock) { | 344 assert LauncherThread.runningOnLauncherThread(); |
358 unbind(); | 345 unbind(); |
359 mService = null; | 346 mService = null; |
360 mConnectionParams = null; | 347 mConnectionParams = null; |
361 } | |
362 } | 348 } |
363 | 349 |
364 private void onServiceConnectedOnLauncherThread(IBinder service) { | 350 private void onServiceConnectedOnLauncherThread(IBinder service) { |
365 assert LauncherThread.runningOnLauncherThread(); | 351 assert LauncherThread.runningOnLauncherThread(); |
366 synchronized (mLock) { | 352 // A flag from the parent class ensures we run the post-connection logic
only once |
367 // A flag from the parent class ensures we run the post-connection l
ogic only once | 353 // (instead of once per each ChildServiceConnection). |
368 // (instead of once per each ChildServiceConnection). | 354 if (mDidOnServiceConnected) { |
369 if (mDidOnServiceConnected) { | 355 return; |
| 356 } |
| 357 try { |
| 358 TraceEvent.begin( |
| 359 "BaseChildProcessConnection.ChildServiceConnection.onService
Connected"); |
| 360 mDidOnServiceConnected = true; |
| 361 mService = IChildProcessService.Stub.asInterface(service); |
| 362 |
| 363 StartCallback startCallback = mStartCallback; |
| 364 mStartCallback = null; |
| 365 |
| 366 final boolean bindCheck = |
| 367 mCreationParams != null && mCreationParams.getBindToCallerCh
eck(); |
| 368 boolean boundToUs = false; |
| 369 try { |
| 370 boundToUs = bindCheck ? mService.bindToCaller() : true; |
| 371 } catch (RemoteException ex) { |
| 372 // Do not trigger the StartCallback here, since the service is a
lready |
| 373 // dead and the DeathCallback will run from onServiceDisconnecte
d(). |
| 374 Log.e(TAG, "Failed to bind service to connection.", ex); |
370 return; | 375 return; |
371 } | 376 } |
372 try { | |
373 TraceEvent.begin( | |
374 "BaseChildProcessConnection.ChildServiceConnection.onSer
viceConnected"); | |
375 mDidOnServiceConnected = true; | |
376 mService = IChildProcessService.Stub.asInterface(service); | |
377 | 377 |
378 StartCallback startCallback = mStartCallback; | 378 if (startCallback != null) { |
379 mStartCallback = null; | 379 if (boundToUs) { |
| 380 startCallback.onChildStarted(); |
| 381 } else { |
| 382 startCallback.onChildStartFailed(); |
| 383 } |
| 384 } |
380 | 385 |
381 final boolean bindCheck = | 386 if (!boundToUs) { |
382 mCreationParams != null && mCreationParams.getBindToCall
erCheck(); | 387 return; |
383 boolean boundToUs = false; | 388 } |
384 try { | |
385 boundToUs = bindCheck ? mService.bindToCaller() : true; | |
386 } catch (RemoteException ex) { | |
387 // Do not trigger the StartCallback here, since the service
is already | |
388 // dead and the DeathCallback will run from onServiceDisconn
ected(). | |
389 Log.e(TAG, "Failed to bind service to connection.", ex); | |
390 return; | |
391 } | |
392 | 389 |
393 if (startCallback != null) { | 390 mServiceConnectComplete = true; |
394 if (boundToUs) { | |
395 startCallback.onChildStarted(); | |
396 } else { | |
397 startCallback.onChildStartFailed(); | |
398 } | |
399 } | |
400 | 391 |
401 if (!boundToUs) { | 392 // Run the setup if the connection parameters have already been prov
ided. If |
402 return; | 393 // not, doConnectionSetupLocked() will be called from setupConnectio
n(). |
403 } | 394 if (mConnectionParams != null) { |
404 | 395 doConnectionSetupLocked(); |
405 mServiceConnectComplete = true; | |
406 | |
407 // Run the setup if the connection parameters have already been
provided. If | |
408 // not, doConnectionSetupLocked() will be called from setupConne
ction(). | |
409 if (mConnectionParams != null) { | |
410 doConnectionSetupLocked(); | |
411 } | |
412 } finally { | |
413 TraceEvent.end( | |
414 "BaseChildProcessConnection.ChildServiceConnection.onSer
viceConnected"); | |
415 } | 396 } |
| 397 } finally { |
| 398 TraceEvent.end("BaseChildProcessConnection.ChildServiceConnection.on
ServiceConnected"); |
416 } | 399 } |
417 } | 400 } |
418 | 401 |
419 private void onServiceDisconnectedOnLauncherThread() { | 402 private void onServiceDisconnectedOnLauncherThread() { |
420 assert LauncherThread.runningOnLauncherThread(); | 403 assert LauncherThread.runningOnLauncherThread(); |
421 synchronized (mLock) { | 404 // Ensure that the disconnection logic runs only once (instead of once p
er each |
422 // Ensure that the disconnection logic runs only once (instead of on
ce per each | 405 // ChildServiceConnection). |
423 // ChildServiceConnection). | 406 if (mServiceDisconnected) { |
424 if (mServiceDisconnected) { | 407 return; |
425 return; | |
426 } | |
427 mServiceDisconnected = true; | |
428 Log.w(TAG, "onServiceDisconnected (crash or killed by oom): pid=%d",
mPid); | |
429 stop(); // We don't want to auto-restart on crash. Let the browser d
o that. | |
430 mDeathCallback.onChildProcessDied(BaseChildProcessConnection.this); | |
431 // If we have a pending connection callback, we need to communicate
the failure to | |
432 // the caller. | |
433 if (mConnectionCallback != null) { | |
434 mConnectionCallback.onConnected(null); | |
435 } | |
436 mConnectionCallback = null; | |
437 } | 408 } |
| 409 mServiceDisconnected = true; |
| 410 Log.w(TAG, "onServiceDisconnected (crash or killed by oom): pid=%d", mPi
d); |
| 411 stop(); // We don't want to auto-restart on crash. Let the browser do th
at. |
| 412 mDeathCallback.onChildProcessDied(BaseChildProcessConnection.this); |
| 413 // If we have a pending connection callback, we need to communicate the
failure to |
| 414 // the caller. |
| 415 if (mConnectionCallback != null) { |
| 416 mConnectionCallback.onConnected(null); |
| 417 } |
| 418 mConnectionCallback = null; |
438 } | 419 } |
439 | 420 |
440 private void onSetupConnectionResult(int pid) { | 421 private void onSetupConnectionResult(int pid) { |
441 synchronized (mLock) { | 422 mPid = pid; |
442 mPid = pid; | 423 assert mPid != 0 : "Child service claims to be run by a process of pid=0
."; |
443 assert mPid != 0 : "Child service claims to be run by a process of p
id=0."; | |
444 | 424 |
445 if (mConnectionCallback != null) { | 425 if (mConnectionCallback != null) { |
446 mConnectionCallback.onConnected(this); | 426 mConnectionCallback.onConnected(this); |
447 } | |
448 mConnectionCallback = null; | |
449 } | 427 } |
| 428 mConnectionCallback = null; |
450 } | 429 } |
451 | 430 |
452 /** | 431 /** |
453 * Called after the connection parameters have been set (in setupConnection(
)) *and* a | 432 * Called after the connection parameters have been set (in setupConnection(
)) *and* a |
454 * connection has been established (as signaled by onServiceConnected()). Th
ese two events can | 433 * connection has been established (as signaled by onServiceConnected()). Th
ese two events can |
455 * happen in any order. Has to be called with mLock. | 434 * happen in any order. Has to be called with mLock. |
456 */ | 435 */ |
457 @GuardedBy("mLock") | |
458 private void doConnectionSetupLocked() { | 436 private void doConnectionSetupLocked() { |
459 try { | 437 try { |
460 TraceEvent.begin("BaseChildProcessConnection.doConnectionSetupLocked
"); | 438 TraceEvent.begin("BaseChildProcessConnection.doConnectionSetupLocked
"); |
461 assert mServiceConnectComplete && mService != null; | 439 assert mServiceConnectComplete && mService != null; |
462 assert mConnectionParams != null; | 440 assert mConnectionParams != null; |
463 | 441 |
464 Bundle bundle = ChildProcessLauncher.createsServiceBundle( | 442 Bundle bundle = ChildProcessLauncher.createsServiceBundle( |
465 mConnectionParams.mCommandLine, mConnectionParams.mFilesToBe
Mapped); | 443 mConnectionParams.mCommandLine, mConnectionParams.mFilesToBe
Mapped); |
466 ICallbackInt pidCallback = new ICallbackInt.Stub() { | 444 ICallbackInt pidCallback = new ICallbackInt.Stub() { |
467 @Override | 445 @Override |
(...skipping 23 matching lines...) Expand all Loading... |
491 } finally { | 469 } finally { |
492 TraceEvent.end("BaseChildProcessConnection.doConnectionSetupLocked")
; | 470 TraceEvent.end("BaseChildProcessConnection.doConnectionSetupLocked")
; |
493 } | 471 } |
494 } | 472 } |
495 | 473 |
496 /** Subclasses should implement this method to bind/unbind to the actual ser
vice. */ | 474 /** Subclasses should implement this method to bind/unbind to the actual ser
vice. */ |
497 protected abstract boolean bind(); | 475 protected abstract boolean bind(); |
498 protected abstract void unbind(); | 476 protected abstract void unbind(); |
499 | 477 |
500 protected ChildServiceConnection createServiceConnection(int bindFlags) { | 478 protected ChildServiceConnection createServiceConnection(int bindFlags) { |
| 479 assert LauncherThread.runningOnLauncherThread(); |
501 return new ChildServiceConnectionImpl(bindFlags); | 480 return new ChildServiceConnectionImpl(bindFlags); |
502 } | 481 } |
503 | 482 |
504 protected boolean shouldBindAsExportedService() { | 483 protected boolean shouldBindAsExportedService() { |
| 484 assert LauncherThread.runningOnLauncherThread(); |
505 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && getCreationPara
ms() != null | 485 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && getCreationPara
ms() != null |
506 && getCreationParams().getIsExternalService() | 486 && getCreationParams().getIsExternalService() |
507 && isExportedService(isSandboxed(), getContext(), getServiceName
()); | 487 && isExportedService(isSandboxed(), getContext(), getServiceName
()); |
508 } | 488 } |
509 | 489 |
510 private static boolean isExportedService( | 490 private static boolean isExportedService( |
511 boolean inSandbox, Context context, ComponentName serviceName) { | 491 boolean inSandbox, Context context, ComponentName serviceName) { |
512 // Check for the cached value first. It is assumed that all pooled child
services | 492 // Check for the cached value first. It is assumed that all pooled child
services |
513 // have identical attributes in the manifest. | 493 // have identical attributes in the manifest. |
514 final int arrayIndex = inSandbox ? 1 : 0; | 494 final int arrayIndex = inSandbox ? 1 : 0; |
515 if (sNeedsExtrabindFlags[arrayIndex] != null) { | 495 if (sNeedsExtrabindFlags[arrayIndex] != null) { |
516 return sNeedsExtrabindFlags[arrayIndex].booleanValue(); | 496 return sNeedsExtrabindFlags[arrayIndex].booleanValue(); |
517 } | 497 } |
518 boolean result = false; | 498 boolean result = false; |
519 try { | 499 try { |
520 PackageManager packageManager = context.getPackageManager(); | 500 PackageManager packageManager = context.getPackageManager(); |
521 ServiceInfo serviceInfo = packageManager.getServiceInfo(serviceName,
0); | 501 ServiceInfo serviceInfo = packageManager.getServiceInfo(serviceName,
0); |
522 result = serviceInfo.exported; | 502 result = serviceInfo.exported; |
523 } catch (PackageManager.NameNotFoundException e) { | 503 } catch (PackageManager.NameNotFoundException e) { |
524 Log.e(TAG, "Could not retrieve info about service %s", serviceName,
e); | 504 Log.e(TAG, "Could not retrieve info about service %s", serviceName,
e); |
525 } | 505 } |
526 sNeedsExtrabindFlags[arrayIndex] = Boolean.valueOf(result); | 506 sNeedsExtrabindFlags[arrayIndex] = Boolean.valueOf(result); |
527 return result; | 507 return result; |
528 } | 508 } |
529 | 509 |
530 @VisibleForTesting | 510 @VisibleForTesting |
531 public void crashServiceForTesting() throws RemoteException { | 511 public void crashServiceForTesting() throws RemoteException { |
532 synchronized (mLock) { | 512 mService.crashIntentionallyForTesting(); |
533 mService.crashIntentionallyForTesting(); | |
534 } | |
535 } | 513 } |
536 | 514 |
537 @VisibleForTesting | 515 @VisibleForTesting |
538 public boolean isConnected() { | 516 boolean isConnected() { |
539 synchronized (mLock) { | 517 return mService != null; |
540 return mService != null; | |
541 } | |
542 } | 518 } |
543 } | 519 } |
OLD | NEW |