// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/sys/sysmgr/app.h"

#include <fuchsia/io/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/default.h>
#include <lib/async/dispatcher.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/cpp/clone.h>
#include <lib/fidl/cpp/interface_handle.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/vfs/cpp/service.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
namespace sysmgr {
namespace {
constexpr char kDefaultLabel[] = "sys";
#ifdef AUTO_UPDATE_PACKAGES
constexpr bool kAutoUpdatePackages = true;
#else
constexpr bool kAutoUpdatePackages = false;
#endif
}  // namespace

App::App(Config config, std::shared_ptr<sys::ServiceDirectory> incoming_services, async::Loop* loop)
    : loop_(loop),
      incoming_services_(std::move(incoming_services)),
      auto_updates_enabled_(kAutoUpdatePackages),
      power_admin_(incoming_services_->Connect<fuchsia::hardware::power::statecontrol::Admin>()) {
  const auto critical_components = config.TakeCriticalComponents();
  for (const auto& url : critical_components) {
    critical_components_.insert(url);
  }
  // The set of excluded services below are services that are the transitive
  // closure of dependencies required for auto-updates that must not be resolved
  // via the update service.
  const auto update_dependencies = config.TakeUpdateDependencies();
  const auto optional_services = config.TakeOptionalServices();
  std::unordered_set<std::string> update_dependency_urls;

  // Register services.
  for (auto& pair : config.TakeServices()) {
    if (std::find(update_dependencies.begin(), update_dependencies.end(), pair.first) !=
        std::end(update_dependencies)) {
      update_dependency_urls.insert(pair.second->url);
    }
    const bool optional = std::find(optional_services.begin(), optional_services.end(),
                                    pair.first) != std::end(optional_services);
    RegisterSingleton(pair.first, std::move(pair.second), optional);
  }

  auto env_request = env_.NewRequest();
  fuchsia::sys::ServiceProviderPtr env_services;
  env_->GetLauncher(env_launcher_.NewRequest());
  env_->GetServices(env_services.NewRequest());

  if (auto_updates_enabled_) {
    const bool resolver_missing =
        std::find(update_dependencies.begin(), update_dependencies.end(),
                  fuchsia::pkg::PackageResolver::Name_) == update_dependencies.end();
    // Check if any component urls that are excluded (dependencies of
    // PackageResolver/startup) were not registered from the above
    // configuration.
    bool missing_services = false;
    for (auto& dep : update_dependencies) {
      if (std::find(svc_names_.begin(), svc_names_.end(), dep) == svc_names_.end()) {
        FX_LOGS(WARNING) << "missing service required for auto updates: " << dep;
        missing_services = true;
      }
    }

    if (resolver_missing || missing_services) {
      FX_LOGS(WARNING) << "auto_update_packages = true but some update "
                          "dependencies are missing in the sys environment. "
                          "Disabling auto-updates.";
      auto_updates_enabled_ = false;
    }
  }

  // Configure loader.
  if (auto_updates_enabled_) {
    package_updating_loader_ = std::make_unique<PackageUpdatingLoader>(
        std::move(update_dependency_urls), std::move(env_services), async_get_default_dispatcher());
  }
  static const char* const kLoaderName = fuchsia::sys::Loader::Name_;
  auto child =
      std::make_unique<vfs::Service>([this](zx::channel channel, async_dispatcher_t* dispatcher) {
        if (auto_updates_enabled_) {
          package_updating_loader_->Bind(
              fidl::InterfaceRequest<fuchsia::sys::Loader>(std::move(channel)));
        } else {
          incoming_services_->Connect(kLoaderName, std::move(channel));
        }
      });
  svc_names_.push_back(kLoaderName);
  svc_root_.AddEntry(kLoaderName, std::move(child));

  // Set up environment for the programs we will run.
  fuchsia::sys::ServiceListPtr service_list(new fuchsia::sys::ServiceList);
  service_list->names = std::move(svc_names_);
  service_list->host_directory = OpenAsDirectory();
  fuchsia::sys::EnvironmentPtr environment;
  incoming_services_->Connect(environment.NewRequest());
  // Inherit services from the root appmgr realm, which includes certain
  // services currently implemented by non-component processes that are passed
  // through appmgr to this sys realm. Note that |service_list| will override
  // the inherited services if it includes services also in the root realm.
  fuchsia::sys::EnvironmentOptions options = {.inherit_parent_services = true};
  environment->CreateNestedEnvironment(std::move(env_request), env_controller_.NewRequest(),
                                       kDefaultLabel, std::move(service_list), std::move(options));

  // Connect to startup services
  for (auto& startup_service : config.TakeStartupServices()) {
    FX_VLOGS(1) << "Connecting to startup service " << startup_service;
    zx::channel h1, h2;
    zx::channel::create(0, &h1, &h2);
    ConnectToService(startup_service, std::move(h1));
  }

  // Launch startup applications.
  for (auto& launch_info : config.TakeApps()) {
    LaunchComponent(std::move(*launch_info), nullptr, nullptr);
  }
}

App::~App() = default;

zx::channel App::OpenAsDirectory() {
  fidl::InterfaceHandle<fuchsia::io::Directory> dir;
  svc_root_.Serve(fuchsia::io::OPEN_RIGHT_READABLE | fuchsia::io::OPEN_RIGHT_WRITABLE,
                  dir.NewRequest().TakeChannel());
  return dir.TakeChannel();
}

void App::ConnectToService(const std::string& service_name, zx::channel channel) {
  vfs::internal::Node* child;
  auto status = svc_root_.Lookup(service_name, &child);
  if (status == ZX_OK) {
    status = child->Serve(fuchsia::io::OPEN_RIGHT_READABLE, std::move(channel));
  }
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Could not serve " << service_name << ": " << status;
  }
}

void App::RegisterSingleton(std::string service_name, fuchsia::sys::LaunchInfoPtr launch_info,
                            bool is_optional_service) {
  // The ComponentController is kept alive under the following functor's state.
  auto child = std::make_unique<vfs::Service>(
      [this, is_optional_service, service_name, launch_info = std::move(launch_info),
       controller = fuchsia::sys::ComponentControllerPtr()](
          zx::channel client_handle, async_dispatcher_t* dispatcher) mutable {
        FX_VLOGS(2) << "Servicing singleton service request for " << service_name;
        std::shared_ptr<sys::ServiceDirectory> svcs;

        auto it = services_.find(launch_info->url);
        // Start component if it isn't already running
        if (it == services_.end()) {
          FX_VLOGS(1) << "Starting singleton " << launch_info->url << " for service "
                      << service_name;
          LaunchComponent(
              *launch_info,
              [is_optional_service, service_name, url = launch_info->url](
                  int64_t, fuchsia::sys::TerminationReason reason) {
                if (!is_optional_service &&
                    reason == fuchsia::sys::TerminationReason::PACKAGE_NOT_FOUND) {
                  FX_LOGS(ERROR) << "Could not load package for service " << service_name << " at "
                                 << url;
                }
              },
              [is_optional_service, url = launch_info->url](zx_status_t) {
                if (!is_optional_service) {
                  FX_LOGS(ERROR) << "Singleton component " << url << " died";
                }
              });
          it = services_.find(launch_info->url);
          FX_DCHECK(it != services_.end());
        }
        it->second->Connect(service_name, std::move(client_handle));
      });
  svc_names_.push_back(service_name);
  svc_root_.AddEntry(service_name, std::move(child));
}

void App::LaunchComponent(const fuchsia::sys::LaunchInfo& launch_info,
                          fuchsia::sys::ComponentController::OnTerminatedCallback on_terminate,
                          fit::function<void(zx_status_t)> on_ctrl_err) {
  FX_VLOGS(1) << "Launching component " << launch_info.url;

  const auto& critical_it = critical_components_.find(launch_info.url);
  const bool is_critical = critical_it != critical_components_.end();
  fuchsia::sys::ComponentControllerPtr ctrl;
  ctrl.events().OnTerminated = std::move(on_terminate);
  ctrl.set_error_handler([this, on_ctrl_err = std::move(on_ctrl_err), url = launch_info.url,
                          is_critical](zx_status_t status) mutable {
    // move the controller on to the stack first before removing it from |controllers_|; otherwise,
    // this lambda's lifetime ends when we remove the controller from |controllers_|.
    auto ctrl = std::move(controllers_[url]);
    controllers_.erase(url);
    if (on_ctrl_err) {
      on_ctrl_err(status);
    }
    if (is_critical) {
      RebootFromCriticalComponent(url);
    } else {
      services_.erase(url);
    }
  });

  // Launch the component
  fuchsia::sys::LaunchInfo dup_launch_info;
  dup_launch_info.url = launch_info.url;
  services_.emplace(launch_info.url,
                    sys::ServiceDirectory::CreateWithRequest(&dup_launch_info.directory_request));
  fidl::Clone(launch_info.arguments, &dup_launch_info.arguments);
  env_launcher_->CreateComponent(std::move(dup_launch_info), ctrl.NewRequest());
  controllers_[launch_info.url] = std::move(ctrl);
}

void App::RebootFromCriticalComponent(const std::string& component_url) {
  FX_LOGS(ERROR) << "Critical component " << component_url << " has crashed.  Rebooting system.";
  power_admin_->Reboot(
      fuchsia::hardware::power::statecontrol::RebootReason::CRITICAL_COMPONENT_FAILURE,
      [this](fuchsia::hardware::power::statecontrol::Admin_Reboot_Result status) {
        if (status.is_err()) {
          FX_PLOGS(FATAL, status.err()) << "Failed to reboot";
          loop_->Quit();
        }
      });
}

}  // namespace sysmgr
