// 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 "lib/inspect/cpp/inspector.h"
#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/storage/vfs/cpp/pseudo_dir.h"
#include "src/lib/storage/vfs/cpp/service.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::MakeRefCounted<fs::PseudoDir>()),
      sysmgr_url_(std::move(args.sysmgr_url)),
      sysmgr_args_(std::move(args.sysmgr_args)),
      storage_watchdog_(StorageWatchdog(kRootDataDir, kRootCacheDir)),
      storage_metrics_(
          {
              "/data/cache",
              "/data/persistent",
          },
          inspector_.GetRoot().CreateChild("storage_usage")),
      lifecycle_server_(this, std::move(args.stop_callback)),
      lifecycle_executor_(dispatcher),
      lifecycle_allowlist_(std::move(args.lifecycle_allowlist)),
      startup_service_() {
  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);
  if (zx_status_t status = storage_metrics_.Run().status_value() != ZX_OK) {
    FX_LOGS(WARNING) << "Failed to start polling storage usage: " << zx_status_get_string(status);
  }

  // 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::MakeRefCounted<fs::RemoteDir>(std::move(svc_client_chan));
    auto diagnostics = fbl::MakeRefCounted<fs::PseudoDir>();
    diagnostics->AddEntry(
        fuchsia::inspect::Tree::Name_,
        fbl::MakeRefCounted<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::MakeRefCounted<fs::PseudoDir>();
    appmgr_svc->AddEntry(
        fuchsia::sys::internal::LogConnector::Name_,
        fbl::MakeRefCounted<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::MakeRefCounted<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::MakeRefCounted<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::MeasureCpu(async_dispatcher_t* dispatcher) {
  cpu_watcher_->Measure();

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

}  // namespace component
