// Copyright 2018 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/appmgr/appmgr.h"

#include <fcntl.h>
#include <fuchsia/appmgr/cpp/fidl.h>
#include <fuchsia/hardware/power/statecontrol/cpp/fidl.h>
#include <fuchsia/process/lifecycle/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/fit/single_threaded_executor.h>
#include <lib/inspect/service/cpp/service.h>
#include <lib/sys/cpp/termination_reason.h>
#include <lib/zx/time.h>
#include <zircon/errors.h>
#include <zircon/status.h>

#include <memory>
#include <vector>

#include <fbl/ref_ptr.h>
#include <fs/pseudo_dir.h>
#include <fs/service.h>

#include "lib/inspect/cpp/inspector.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/sys/appmgr/constants.h"
#include "src/sys/appmgr/startup_service.h"

using fuchsia::sys::TerminationReason;

namespace component {
namespace {
constexpr zx::duration kCpuSamplePeriod = zx::min(1);
constexpr size_t kMaxInspectSize = 2 * 1024 * 1024 /* 2MB */;
}  // namespace

Appmgr::Appmgr(async_dispatcher_t* dispatcher, AppmgrArgs args)
    : inspector_(inspect::InspectSettings{.maximum_size = kMaxInspectSize}),
      cpu_watcher_(
          std::make_unique<CpuWatcher>(inspector_.GetRoot().CreateChild("cpu_stats"), zx::job())),
      publish_vfs_(dispatcher),
      publish_dir_(fbl::AdoptRef(new fs::PseudoDir())),
      sysmgr_url_(std::move(args.sysmgr_url)),
      sysmgr_args_(std::move(args.sysmgr_args)),
      storage_watchdog_(StorageWatchdog(kRootDataDir, kRootCacheDir)),
      lifecycle_server_(this, std::move(args.stop_callback)),
      lifecycle_executor_(dispatcher),
      lifecycle_allowlist_(std::move(args.lifecycle_allowlist)),
      startup_service_() {
  RecordSelfCpuStats();
  inspector_.GetRoot().CreateLazyNode(
      "inspect_stats",
      [this] {
        inspect::InspectStats stats = inspector_.GetStats();
        inspect::Inspector insp;
        insp.GetRoot().CreateUint("current_size", stats.size, &insp);
        insp.GetRoot().CreateUint("maximum_size", stats.maximum_size, &insp);
        insp.GetRoot().CreateUint("dynamic_links", stats.dynamic_child_count, &insp);
        return fit::make_result_promise(fit::ok(std::move(insp)));
      },
      &inspector_);

  // 0. Start storage watchdog for cache storage
  storage_watchdog_.Run(dispatcher);

  // 1. Create root realm.
  fbl::unique_fd appmgr_config_dir(
      open("/pkgfs/packages/config-data/0/meta/data/appmgr", O_RDONLY));
  if (!appmgr_config_dir.is_valid()) {
    FX_LOGS(ERROR) << "Could not open appmgr's config dir. error = " << appmgr_config_dir.get();
  }
  fit::result<fbl::RefPtr<ComponentIdIndex>, ComponentIdIndex::Error> component_id_index =
      ComponentIdIndex::CreateFromAppmgrConfigDir(appmgr_config_dir);
  FX_CHECK(component_id_index) << "Cannot read component ID Index. error = "
                               << static_cast<int>(component_id_index.error());

  RealmArgs realm_args;
  if (args.loader) {
    FX_LOGS(INFO) << "Creating root realm with a custom loader";
    realm_args = RealmArgs::MakeWithCustomLoader(
        nullptr, internal::kRootLabel, kRootDataDir, kRootCacheDir, kRootTempDir,
        std::move(args.environment_services), args.run_virtual_console,
        std::move(args.root_realm_services), fuchsia::sys::EnvironmentOptions{},
        std::move(appmgr_config_dir), component_id_index.take_value(),
        std::move(args.loader.value()));
  } else {
    realm_args = RealmArgs::MakeWithAdditionalServices(
        nullptr, internal::kRootLabel, kRootDataDir, kRootCacheDir, kRootTempDir,
        std::move(args.environment_services), args.run_virtual_console,
        std::move(args.root_realm_services), fuchsia::sys::EnvironmentOptions{},
        std::move(appmgr_config_dir), component_id_index.take_value());
  }
  realm_args.cpu_watcher = cpu_watcher_.get();
  root_realm_ = Realm::Create(std::move(realm_args));
  FX_CHECK(root_realm_) << "Cannot create root realm ";

  // 2. Listen for lifecycle requests
  zx_status_t status;
  if (args.lifecycle_request != ZX_HANDLE_INVALID) {
    status = lifecycle_server_.Create(dispatcher, zx::channel(std::move(args.lifecycle_request)));
    if (status != ZX_OK) {
      FX_PLOGS(ERROR, status) << "Failed to bind lifecycle service.";
      return;
    }
  }

  // 3. Prepare to run sysmgr and install callback to actually start it once the
  //    logs are connected.
  auto run_sysmgr = [this, dispatcher] {
    fuchsia::sys::LaunchInfo launch_info;
    launch_info.url = sysmgr_url_;
    launch_info.arguments = fidl::Clone(sysmgr_args_);
    sysmgr_.events().OnDirectoryReady = [this] { sysmgr_running_ = true; };
    sysmgr_.events().OnTerminated = [dispatcher](zx_status_t exit_code,
                                                 TerminationReason termination_reason) {
      // If sysmgr exited for any reason, something went wrong, so trigger reboot.
      FX_LOGS(ERROR) << "sysmgr exited with status " << exit_code;
      fuchsia::hardware::power::statecontrol::AdminPtr power_admin;
      zx_status_t status =
          fdio_service_connect("/svc/fuchsia.hardware.power.statecontrol.Admin",
                               power_admin.NewRequest(dispatcher).TakeChannel().release());
      FX_CHECK(status == ZX_OK) << "Could not connect to power state control service: "
                                << zx_status_get_string(status);
      const auto reason = fuchsia::hardware::power::statecontrol::RebootReason::SYSMGR_FAILURE;
      auto cb = [](fuchsia::hardware::power::statecontrol::Admin_Reboot_Result result) {
        if (result.is_err()) {
          FX_LOGS(FATAL) << "Failed to reboot after sysmgr exited: "
                         << zx_status_get_string(result.err());
        }
      };
      power_admin->Reboot(reason, cb);
    };
    root_realm_->CreateComponent(std::move(launch_info), sysmgr_.NewRequest());
  };
  root_realm_->log_connector()->OnReady(run_sysmgr);

  // 4. Publish outgoing directories.
  // Connect to the tracing service, and then publish the root realm's hub
  // directory as 'hub/' and the first nested realm's (to be created by sysmgr)
  // service directory as 'svc/'.
  zx::channel svc_client_chan, svc_server_chan;
  status = zx::channel::create(0, &svc_client_chan, &svc_server_chan);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to create channel: " << status;
    return;
  }
  status = root_realm_->BindFirstNestedRealmSvc(std::move(svc_server_chan));
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "failed to bind to root realm services: " << status;
    return;
  }
  status = fdio_service_connect_at(svc_client_chan.get(), "fuchsia.tracing.provider.Registry",
                                   args.trace_server_channel.release());
  if (status != ZX_OK) {
    FX_LOGS(WARNING) << "failed to connect to tracing: " << status;
    // In test environments the tracing registry may not be available. If this
    // fails, let's still proceed.
  }

  if (args.pa_directory_request != ZX_HANDLE_INVALID) {
    auto svc = fbl::AdoptRef(new fs::RemoteDir(std::move(svc_client_chan)));
    auto diagnostics = fbl::AdoptRef(new fs::PseudoDir());
    diagnostics->AddEntry(
        fuchsia::inspect::Tree::Name_,
        fbl::AdoptRef(new fs::Service(
            [connector = inspect::MakeTreeHandler(&inspector_)](zx::channel chan) mutable {
              connector(fidl::InterfaceRequest<fuchsia::inspect::Tree>(std::move(chan)));
              return ZX_OK;
            })));

    // The following are services that appmgr exposes to the v2 world, but doesn't
    // expose to the sys realm.
    auto appmgr_svc = fbl::AdoptRef(new fs::PseudoDir());
    appmgr_svc->AddEntry(
        fuchsia::sys::internal::LogConnector::Name_,
        fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
          fidl::InterfaceRequest<fuchsia::sys::internal::LogConnector> request(std::move(channel));
          root_realm_->log_connector()->AddConnectorClient(std::move(request));
          return ZX_OK;
        })));
    appmgr_svc->AddEntry(
        fuchsia::sys::internal::ComponentEventProvider::Name_,
        fbl::AdoptRef(new fs::Service([this](zx::channel channel) {
          return root_realm_->BindComponentEventProvider(
              fidl::InterfaceRequest<fuchsia::sys::internal::ComponentEventProvider>(
                  std::move(channel)));
        })));

    appmgr_svc->AddEntry(
        fuchsia::appmgr::Startup::Name_,
        fbl::AdoptRef(new fs::Service([this, dispatcher](zx::channel channel) {
          return startup_service_.Bind(
              dispatcher, fidl::InterfaceRequest<fuchsia::appmgr::Startup>(std::move(channel)));
        })));

    publish_dir_->AddEntry("hub", root_realm_->hub_dir());
    publish_dir_->AddEntry("svc", svc);
    publish_dir_->AddEntry("diagnostics", diagnostics);
    publish_dir_->AddEntry("appmgr_svc", appmgr_svc);
    publish_vfs_.ServeDirectory(publish_dir_, zx::channel(args.pa_directory_request));
  }

  async::PostTask(dispatcher, [this, dispatcher] { MeasureCpu(dispatcher); });
}

Appmgr::~Appmgr() = default;

void Appmgr::FindLifecycleComponentsInRealm(Realm* realm,
                                            std::vector<LifecycleComponent>* lifecycle_components) {
  // Look through child realms
  for (auto it = realm->children().begin(); it != realm->children().end(); ++it) {
    FindLifecycleComponentsInRealm(it->first, lifecycle_components);
  }

  // Look for applications in the lifecycle allow list
  auto applications = realm->applications();
  for (auto it = applications.begin(); it != applications.end(); ++it) {
    auto controller = it->first;

    FuchsiaPkgUrl package_url;
    package_url.Parse(controller->url());
    Moniker component_moniker = Realm::ComputeMoniker(realm, package_url);

    if (lifecycle_allowlist_.find(component_moniker) == lifecycle_allowlist_.end()) {
      continue;
    }

    FX_LOGS(INFO) << component_moniker.url << " is in the lifecycle allow list.";
    lifecycle_components->emplace_back(it->second, component_moniker);
  }
}

struct ShutdownCountdown {
  int component_count;
  fit::function<void(zx_status_t)> complete_callback;

  ShutdownCountdown(int component_count, fit::function<void(zx_status_t)> complete_callback)
      : component_count(component_count), complete_callback(std::move(complete_callback)) {}
};

std::vector<std::shared_ptr<fuchsia::process::lifecycle::LifecyclePtr>> Appmgr::Shutdown(
    fit::function<void(zx_status_t)> callback) {
  FX_LOGS(INFO) << "appmgr shutdown called.";

  std::vector<LifecycleComponent> lifecycle_components;
  FindLifecycleComponentsInRealm(root_realm_.get(), &lifecycle_components);

  auto components_remaining =
      std::make_shared<ShutdownCountdown>(lifecycle_components.size(), std::move(callback));

  std::vector<std::shared_ptr<fuchsia::process::lifecycle::LifecyclePtr>> child_lifecycles;

  if (components_remaining->component_count == 0) {
    FX_LOGS(INFO) << "No components expose lifecycle, continuing appmgr shutdown.";
    components_remaining->complete_callback(ZX_OK);
    return child_lifecycles;
  }

  // Schedule tasks to shutdown the running lifecycle components. These tasks will be performed
  // concurrently.
  for (auto& component : lifecycle_components) {
    auto lifecycle = std::make_shared<fuchsia::process::lifecycle::LifecyclePtr>();
    child_lifecycles.push_back(lifecycle);
    // Connect to its lifecycle service and tell it to shutdown.
    lifecycle_executor_.schedule_task(component.controller->GetServiceDir().and_then(
        [components_remaining, component = std::move(component),
         lifecycle](fidl::InterfaceHandle<fuchsia::io::Directory>& dir) {
          // The lifecycle_allowlist_ contains v1 components which expose their services over svc/
          // instead of the PA_LIFECYCLE channel.

          zx_status_t status = fdio_service_connect_at(
              dir.TakeChannel().release(), "fuchsia.process.lifecycle.Lifecycle",
              lifecycle->NewRequest().TakeChannel().release());
          if (status != ZX_OK) {
            FX_LOGS(ERROR) << "Failed to connect to fuchsia.process.lifecycle.Lifecycle for "
                           << component.moniker.url << ".";
            return;
          }

          lifecycle->set_error_handler(
              [components_remaining, url = component.moniker.url](zx_status_t status) {
                components_remaining->component_count--;
                if (components_remaining->component_count == 0) {
                  FX_LOGS(INFO) << "All lifecycle components shut down.";
                  components_remaining->complete_callback(ZX_OK);
                }
              });
          lifecycle->get()->Stop();

          // Keep the lifecycle from being destroyed to ensure the channel stays open.
        }));
  }
  return child_lifecycles;
}

void Appmgr::RecordSelfCpuStats() {
  zx::job my_job;
  zx_info_handle_basic_t info = {};
  zx_status_t err = zx::job::default_job()->duplicate(ZX_RIGHT_SAME_RIGHTS, &my_job);
  if (err != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to initialize job " << err;
  } else {
    err = my_job.get_info(ZX_INFO_HANDLE_BASIC, &info, sizeof(info), nullptr, nullptr);
    if (err != ZX_OK) {
      FX_LOGS(ERROR) << "Failed to get job info " << err;
    }
  }
  cpu_watcher_->AddTask({"appmgr.cm", std::to_string(info.koid)}, std::move(my_job));
}

void Appmgr::MeasureCpu(async_dispatcher_t* dispatcher) {
  cpu_watcher_->Measure();

  async::PostDelayedTask(
      dispatcher, [this, dispatcher] { MeasureCpu(dispatcher); }, kCpuSamplePeriod);
}

}  // namespace component
