/**
   * Installs the given platform and its dependencies into the given installation, if necessary.
   *
   * @param logger Logs things.
   * @param launcher Used to launch tasks on the remote node.
   * @param sdk SDK installation to install components for.
   * @param platform Specifies the platform to be installed.
   */
  public static void installPlatform(
      PrintStream logger, Launcher launcher, AndroidSdk sdk, String platform)
      throws IOException, InterruptedException {
    // Check whether this platform is already installed
    if (isPlatformInstalled(logger, launcher, sdk, platform)) {
      return;
    }

    // Check whether we are capable of installing individual components
    log(logger, Messages.PLATFORM_INSTALL_REQUIRED(platform));
    if (!launcher.isUnix() && platform.contains(":") && sdk.getSdkToolsVersion() < 16) {
      // SDK add-ons can't be installed on Windows until r16 due to http://b.android.com/18868
      log(logger, Messages.SDK_ADDON_INSTALLATION_UNSUPPORTED());
      return;
    }
    if (!sdk.supportsComponentInstallation()) {
      log(logger, Messages.SDK_COMPONENT_INSTALLATION_UNSUPPORTED());
      return;
    }

    // Automated installation of ABIs (required for android-14+) is not possible until r17, so
    // we should warn the user that we can't automatically set up an AVD with older SDK Tools.
    // See http://b.android.com/21880
    if ((platform.endsWith("14") || platform.endsWith("15"))
        && !sdk.supportsSystemImageInstallation()) {
      log(logger, Messages.ABI_INSTALLATION_UNSUPPORTED(), true);
    }

    // Determine which individual component(s) need to be installed for this platform
    List<String> components = getSdkComponentsForPlatform(logger, platform);
    if (components == null || components.size() == 0) {
      return;
    }

    // If a platform expanded to multiple dependencies (e.g. "GoogleMaps:7" -> android-7 + Maps)
    // then check whether we really need to install android-7, as it may already be installed
    if (components.size() > 1) {
      for (Iterator<String> it = components.iterator(); it.hasNext(); ) {
        String component = it.next();
        if (isPlatformInstalled(logger, launcher, sdk, component)) {
          it.remove();
        }
      }
    }

    // Grab the lock and attempt installation
    Semaphore semaphore = acquireLock();
    try {
      installComponent(logger, launcher, sdk, components.toArray(new String[0]));
    } finally {
      semaphore.release();
    }
  }
  /**
   * Installs the given SDK component(s) into the given installation.
   *
   * @param logger Logs things.
   * @param launcher Used to launch tasks on the remote node.
   * @param sdk Root of the SDK installation to install components for.
   * @param components Name of the component(s) to install.
   */
  private static void installComponent(
      PrintStream logger, Launcher launcher, AndroidSdk sdk, String... components)
      throws IOException, InterruptedException {
    String proxySettings = getProxySettings();

    String list = StringUtils.join(components, ',');
    log(logger, Messages.INSTALLING_SDK_COMPONENTS(list.toString()));
    String all = sdk.getSdkToolsVersion() < 17 ? "-o" : "-a";
    String upgradeArgs = String.format("update sdk -u %s %s -t %s", all, proxySettings, list);

    Utils.runAndroidTool(launcher, logger, logger, sdk, Tool.ANDROID, upgradeArgs, null);
  }