/** Installs the app specified in the constructor. This object should be discarded afterward. */
  public synchronized boolean install(boolean quiet) throws InterruptedException {
    InstallEvent.Started started = InstallEvent.started(apkRule.getBuildTarget());
    eventBus.post(started);

    boolean success =
        adbHelper.adbCall(
            new AdbHelper.AdbCallable() {
              @Override
              public boolean call(IDevice device) throws Exception {
                try {
                  return new SingleDeviceInstaller(device, nextAgentPort.getAndIncrement())
                      .doInstall();
                } catch (Exception e) {
                  throw new RuntimeException("Failed to install exopackage on " + device, e);
                }
              }

              @Override
              public String toString() {
                return "install exopackage";
              }
            },
            quiet);

    eventBus.post(
        InstallEvent.finished(
            started,
            success,
            Optional.<Long>absent(),
            Optional.of(AdbHelper.tryToExtractPackageNameFromManifest(apkRule))));
    return success;
  }
 private static AndroidBinary getUnderlyingApk(InstallableApk installable) {
   if (installable instanceof AndroidBinary) {
     return (AndroidBinary) installable;
   } else if (installable instanceof ApkGenrule) {
     return getUnderlyingApk(((ApkGenrule) installable).getInstallableApk());
   } else {
     throw new IllegalStateException(
         installable.getBuildTarget().getFullyQualifiedName()
             + " must be backed by either an android_binary() or an apk_genrule()");
   }
 }