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

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

Issue 2840303002: Making ChildProcessConnection only accessed from the launcher thread. (Closed)
Patch Set: Clean-up + sync Created 3 years, 7 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 unified diff | Download patch
« no previous file with comments | « no previous file | content/public/android/java/src/org/chromium/content/browser/ManagedChildProcessConnection.java » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | content/public/android/java/src/org/chromium/content/browser/ManagedChildProcessConnection.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698