private boolean isCurrentlyOomProtected() {
   synchronized (mLock) {
     assert !mServiceDisconnected;
     if (mAlwaysInForeground) return ChildProcessLauncher.isApplicationInForeground();
     return mInitialBinding.isBound() || mStrongBinding.isBound();
   }
 }
  @Override
  protected void setUp() throws Exception {
    super.setUp();

    // Hook in the test binding manager.
    mBindingManager = new MockBindingManager();
    ChildProcessLauncher.setBindingManagerForTesting(mBindingManager);
  }
  private void startModerateBindingManagementIfNeeded() {
    // Moderate binding doesn't apply to low end devices.
    if (SysUtils.isLowEndDevice()) return;

    boolean moderateBindingTillBackgrounded =
        FieldTrialList.findFullName("ModerateBindingOnBackgroundTabCreation").equals("Enabled");
    ChildProcessLauncher.startModerateBindingManagement(
        mAppContext, moderateBindingTillBackgrounded);
  }
  /**
   * Verifies that a renderer that crashes in foreground has the correct visibility when recreated.
   */
  @LargeTest
  @Feature({"ProcessManagement"})
  public void testCrashInForeground() throws InterruptedException {
    // Create a tab in foreground and wait until it is loaded.
    final Tab tab =
        ThreadUtils.runOnUiThreadBlockingNoException(
            new Callable<Tab>() {
              @Override
              public Tab call() throws Exception {
                TabCreator tabCreator = getActivity().getCurrentTabCreator();
                return tabCreator.createNewTab(
                    new LoadUrlParams(TestHttpServerClient.getUrl(FILE_PATH)),
                    TabLaunchType.FROM_KEYBOARD,
                    null);
              }
            });
    ChromeTabUtils.waitForTabPageLoaded(tab, TestHttpServerClient.getUrl(FILE_PATH));
    getInstrumentation().waitForIdleSync();

    // Kill the renderer and wait for the crash to be noted by the browser process.
    assertTrue(
        ChildProcessLauncher.crashProcessForTesting(
            tab.getContentViewCore().getCurrentRenderProcessId()));

    assertTrue(
        "Renderer crash wasn't noticed by the browser.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tab.getContentViewCore().getCurrentRenderProcessId() == 0;
              }
            }));

    // Reload the tab, respawning the renderer.
    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                tab.reload();
              }
            });

    // Wait until the process is spawned and its visibility is determined.
    assertTrue(
        "Process for the crashed tab was not respawned.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tab.getContentViewCore().getCurrentRenderProcessId() != 0;
              }
            }));

    assertTrue(
        "isInForeground() was not called for the process.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return mBindingManager.setInForegroundWasCalled(
                    tab.getContentViewCore().getCurrentRenderProcessId());
              }
            }));

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Verify the visibility of the renderer.
                assertTrue(
                    mBindingManager.isInForeground(
                        tab.getContentViewCore().getCurrentRenderProcessId()));
              }
            });
  }
  /**
   * Verifies that the .setProcessInForeground() signal is called correctly when a tab that crashed
   * in background is restored in foreground. This is a regression test for http://crbug.com/399521.
   */
  @LargeTest
  @Feature({"ProcessManagement"})
  public void testCrashInBackground() throws InterruptedException {
    // Create two tabs and wait until they are loaded, so that their renderers are around.
    final Tab[] tabs = new Tab[2];
    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Foreground tab.
                TabCreator tabCreator = getActivity().getCurrentTabCreator();
                tabs[0] =
                    tabCreator.createNewTab(
                        new LoadUrlParams(TestHttpServerClient.getUrl(FILE_PATH)),
                        TabLaunchType.FROM_KEYBOARD,
                        null);
                // Background tab.
                tabs[1] =
                    tabCreator.createNewTab(
                        new LoadUrlParams(TestHttpServerClient.getUrl(FILE_PATH)),
                        TabLaunchType.FROM_LONGPRESS_BACKGROUND,
                        null);
                // On Svelte devices the background tab would not be loaded automatically, so
                // trigger the load manually.
                tabs[1].show(TabSelectionType.FROM_USER);
                tabs[1].hide();
              }
            });
    ChromeTabUtils.waitForTabPageLoaded(tabs[0], TestHttpServerClient.getUrl(FILE_PATH));
    ChromeTabUtils.waitForTabPageLoaded(tabs[1], TestHttpServerClient.getUrl(FILE_PATH));

    // Wait for the new tab animations on phones to finish.
    if (!DeviceFormFactor.isTablet(getActivity()) && getActivity() instanceof ChromeActivity) {
      final ChromeActivity activity = (ChromeActivity) getActivity();
      assertTrue(
          "Did not finish animation",
          CriteriaHelper.pollForUIThreadCriteria(
              new Criteria() {
                @Override
                public boolean isSatisfied() {
                  Layout layout =
                      activity.getCompositorViewHolder().getLayoutManager().getActiveLayout();
                  return !layout.isLayoutAnimating();
                }
              }));
    }
    getInstrumentation().waitForIdleSync();

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Make sure that the renderers were spawned.
                assertTrue(tabs[0].getContentViewCore().getCurrentRenderProcessId() > 0);
                assertTrue(tabs[1].getContentViewCore().getCurrentRenderProcessId() > 0);

                // Verify that the renderer of the foreground tab was signalled as visible.
                assertTrue(
                    mBindingManager.isInForeground(
                        tabs[0].getContentViewCore().getCurrentRenderProcessId()));
                // Verify that the renderer of the tab loaded in background was signalled as not
                // visible.
                assertTrue(
                    mBindingManager.isInBackground(
                        tabs[1].getContentViewCore().getCurrentRenderProcessId()));
              }
            });

    // Kill the renderer and wait for the crash to be noted by the browser process.
    assertTrue(
        ChildProcessLauncher.crashProcessForTesting(
            tabs[1].getContentViewCore().getCurrentRenderProcessId()));

    assertTrue(
        "Renderer crash wasn't noticed by the browser.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tabs[1].getContentViewCore().getCurrentRenderProcessId() == 0;
              }
            }));

    // Switch to the tab that crashed in background.
    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                TabModelUtils.setIndex(getActivity().getCurrentTabModel(), indexOf(tabs[1]));
              }
            });

    // Wait until the process is spawned and its visibility is determined.
    assertTrue(
        "Process for the crashed tab was not respawned.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tabs[1].getContentViewCore().getCurrentRenderProcessId() != 0;
              }
            }));

    assertTrue(
        "isInForeground() was not called for the process.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return mBindingManager.setInForegroundWasCalled(
                    tabs[1].getContentViewCore().getCurrentRenderProcessId());
              }
            }));

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Verify the visibility of the renderers.
                assertTrue(
                    mBindingManager.isInBackground(
                        tabs[0].getContentViewCore().getCurrentRenderProcessId()));
                assertTrue(
                    mBindingManager.isInForeground(
                        tabs[1].getContentViewCore().getCurrentRenderProcessId()));
              }
            });
  }
  /**
   * Verifies that a renderer that crashes in foreground has the correct visibility when recreated.
   */
  @LargeTest
  @Feature({"ProcessManagement"})
  public void testCrashInForeground() throws Exception {
    // Create a tab in foreground and wait until it is loaded.
    final Tab tab =
        ChromeApplication.getDocumentTabModelSelector()
            .getTabById(launchViaViewIntent(false, URL_1, "Page 1"));

    // Kill the renderer and wait for the crash to be noted by the browser process.
    assertTrue(
        ChildProcessLauncher.crashProcessForTesting(
            tab.getContentViewCore().getCurrentRenderProcessId()));

    assertTrue(
        "Renderer crash wasn't noticed by the browser.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tab.getContentViewCore().getCurrentRenderProcessId() == 0;
              }
            }));

    // Reload the tab, respawning the renderer.
    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                tab.reload();
              }
            });

    // Wait until the process is spawned and its visibility is determined.
    assertTrue(
        "Process for the crashed tab was not respawned.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return tab.getContentViewCore().getCurrentRenderProcessId() != 0;
              }
            }));

    assertTrue(
        "isInForeground() was not called for the process.",
        CriteriaHelper.pollForCriteria(
            new Criteria() {
              @Override
              public boolean isSatisfied() {
                return mBindingManager.wasSetInForegroundCalled(
                    tab.getContentViewCore().getCurrentRenderProcessId());
              }
            }));

    getInstrumentation()
        .runOnMainSync(
            new Runnable() {
              @Override
              public void run() {
                // Verify the visibility of the renderer.
                assertTrue(
                    mBindingManager.isInForeground(
                        tab.getContentViewCore().getCurrentRenderProcessId()));
              }
            });
  }