//===-- PlatformAndroid.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/UriParser.h"
#include "lldb/ValueObject/ValueObject.h"

#include "llvm/ADT/DenseMap.h"

#include "AdbClient.h"
#include "PlatformAndroid.h"
#include "PlatformAndroidRemoteGDBServer.h"
#include "lldb/Target/Target.h"
#include <optional>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_android;
using namespace std::chrono;

LLDB_PLUGIN_DEFINE(PlatformAndroid)

namespace {

#define LLDB_PROPERTIES_android
#include "PlatformAndroidProperties.inc"

enum {
#define LLDB_PROPERTIES_android
#include "PlatformAndroidPropertiesEnum.inc"
};

class PluginProperties : public Properties {
public:
  PluginProperties() {
    m_collection_sp = std::make_shared<OptionValueProperties>(
        PlatformAndroid::GetPluginNameStatic(false));
    m_collection_sp->Initialize(g_android_properties_def);
  }
};

static PluginProperties &GetGlobalProperties() {
  static PluginProperties g_settings;
  return g_settings;
}

uint32_t g_initialize_count = 0;
const unsigned int g_android_default_cache_size =
    2048; // Fits inside 4k adb packet.

} // end of anonymous namespace

void PlatformAndroid::Initialize() {
  PlatformLinux::Initialize();

  if (g_initialize_count++ == 0) {
#if defined(__ANDROID__)
    PlatformSP default_platform_sp(new PlatformAndroid(true));
    default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
    Platform::SetHostPlatform(default_platform_sp);
#endif
    PluginManager::RegisterPlugin(
        PlatformAndroid::GetPluginNameStatic(false),
        PlatformAndroid::GetPluginDescriptionStatic(false),
        PlatformAndroid::CreateInstance, PlatformAndroid::DebuggerInitialize);
  }
}

void PlatformAndroid::Terminate() {
  if (g_initialize_count > 0) {
    if (--g_initialize_count == 0) {
      PluginManager::UnregisterPlugin(PlatformAndroid::CreateInstance);
    }
  }

  PlatformLinux::Terminate();
}

PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
  Log *log = GetLog(LLDBLog::Platform);
  if (log) {
    const char *arch_name;
    if (arch && arch->GetArchitectureName())
      arch_name = arch->GetArchitectureName();
    else
      arch_name = "<null>";

    const char *triple_cstr =
        arch ? arch->GetTriple().getTriple().c_str() : "<null>";

    LLDB_LOGF(log, "PlatformAndroid::%s(force=%s, arch={%s,%s})", __FUNCTION__,
              force ? "true" : "false", arch_name, triple_cstr);
  }

  bool create = force;
  if (!create && arch && arch->IsValid()) {
    const llvm::Triple &triple = arch->GetTriple();
    switch (triple.getVendor()) {
    case llvm::Triple::PC:
      create = true;
      break;

#if defined(__ANDROID__)
    // Only accept "unknown" for the vendor if the host is android and if
    // "unknown" wasn't specified (it was just returned because it was NOT
    // specified).
    case llvm::Triple::VendorType::UnknownVendor:
      create = !arch->TripleVendorWasSpecified();
      break;
#endif
    default:
      break;
    }

    if (create) {
      switch (triple.getEnvironment()) {
      case llvm::Triple::Android:
        break;

#if defined(__ANDROID__)
      // Only accept "unknown" for the OS if the host is android and it
      // "unknown" wasn't specified (it was just returned because it was NOT
      // specified)
      case llvm::Triple::EnvironmentType::UnknownEnvironment:
        create = !arch->TripleEnvironmentWasSpecified();
        break;
#endif
      default:
        create = false;
        break;
      }
    }
  }

  if (create) {
    LLDB_LOGF(log, "PlatformAndroid::%s() creating remote-android platform",
              __FUNCTION__);
    return PlatformSP(new PlatformAndroid(false));
  }

  LLDB_LOGF(
      log, "PlatformAndroid::%s() aborting creation of remote-android platform",
      __FUNCTION__);

  return PlatformSP();
}

void PlatformAndroid::DebuggerInitialize(Debugger &debugger) {
  if (!PluginManager::GetSettingForPlatformPlugin(debugger,
                                                  GetPluginNameStatic(false))) {
    PluginManager::CreateSettingForPlatformPlugin(
        debugger, GetGlobalProperties().GetValueProperties(),
        "Properties for the Android platform plugin.",
        /*is_global_property=*/true);
  }
}

PlatformAndroid::PlatformAndroid(bool is_host)
    : PlatformLinux(is_host), m_sdk_version(0) {}

llvm::StringRef PlatformAndroid::GetPluginDescriptionStatic(bool is_host) {
  if (is_host)
    return "Local Android user platform plug-in.";
  return "Remote Android user platform plug-in.";
}

Status PlatformAndroid::ConnectRemote(Args &args) {
  m_device_id.clear();

  if (IsHost())
    return Status::FromErrorString(
        "can't connect to the host platform, always connected");

  if (!m_remote_platform_sp)
    m_remote_platform_sp = PlatformSP(new PlatformAndroidRemoteGDBServer());

  const char *url = args.GetArgumentAtIndex(0);
  if (!url)
    return Status::FromErrorString("URL is null.");
  std::optional<URI> parsed_url = URI::Parse(url);
  if (!parsed_url)
    return Status::FromErrorStringWithFormat("Invalid URL: %s", url);
  if (parsed_url->hostname != "localhost")
    m_device_id = parsed_url->hostname.str();

  auto error = PlatformLinux::ConnectRemote(args);
  if (error.Success()) {
    auto resolved_device_id_or_error = AdbClient::ResolveDeviceID(m_device_id);
    if (!resolved_device_id_or_error)
      return Status::FromError(resolved_device_id_or_error.takeError());
    m_device_id = *resolved_device_id_or_error;
  }
  return error;
}

Status PlatformAndroid::GetFile(const FileSpec &source,
                                const FileSpec &destination) {
  if (IsHost() || !m_remote_platform_sp)
    return PlatformLinux::GetFile(source, destination);

  FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix);
  if (source_spec.IsRelative())
    source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
        source_spec.GetPath(false));

  Status error;
  auto sync_service = GetSyncService(error);

  // If sync service is available, try to use it
  if (error.Success() && sync_service) {
    uint32_t mode = 0, size = 0, mtime = 0;
    error = sync_service->Stat(source_spec, mode, size, mtime);
    if (error.Success()) {
      if (mode != 0)
        return sync_service->PullFile(source_spec, destination);

      // mode == 0 can signify that adbd cannot access the file due security
      // constraints - fall through to try "cat ..." as a fallback.
      Log *log = GetLog(LLDBLog::Platform);
      LLDB_LOGF(log, "Got mode == 0 on '%s': try to get file via 'shell cat'",
                source_spec.GetPath(false).c_str());
    }
  }

  // Fallback to shell cat command if sync service failed or returned mode == 0
  std::string source_file = source_spec.GetPath(false);

  Log *log = GetLog(LLDBLog::Platform);
  LLDB_LOGF(log, "Using shell cat fallback for '%s'", source_file.c_str());

  if (strchr(source_file.c_str(), '\'') != nullptr)
    return Status::FromErrorString(
        "Doesn't support single-quotes in filenames");

  AdbClientUP adb(GetAdbClient(error));
  if (error.Fail())
    return error;

  char cmd[PATH_MAX];
  snprintf(cmd, sizeof(cmd), "%scat '%s'", GetRunAs().c_str(),
           source_file.c_str());

  return adb->ShellToFile(cmd, minutes(1), destination);
}

Status PlatformAndroid::PutFile(const FileSpec &source,
                                const FileSpec &destination, uint32_t uid,
                                uint32_t gid) {
  if (IsHost() || !m_remote_platform_sp)
    return PlatformLinux::PutFile(source, destination, uid, gid);

  FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix);
  if (destination_spec.IsRelative())
    destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
        destination_spec.GetPath(false));

  // TODO: Set correct uid and gid on remote file.
  Status error;
  auto sync_service = GetSyncService(error);
  if (error.Fail())
    return error;
  return sync_service->PushFile(source, destination_spec);
}

const char *PlatformAndroid::GetCacheHostname() { return m_device_id.c_str(); }

Status PlatformAndroid::DownloadModuleSlice(const FileSpec &src_file_spec,
                                            const uint64_t src_offset,
                                            const uint64_t src_size,
                                            const FileSpec &dst_file_spec) {
  std::string source_file = src_file_spec.GetPath(false);
  if (source_file.empty())
    return Status::FromErrorString("Source file path cannot be empty");

  std::string destination_file = dst_file_spec.GetPath(false);
  if (destination_file.empty())
    return Status::FromErrorString("Destination file path cannot be empty");

  // In Android API level 23 and above, dynamic loader is able to load .so
  // file directly from APK. In that case, src_offset will be an non-zero.
  if (src_offset == 0) // Use GetFile for a normal file.
    return GetFile(src_file_spec, dst_file_spec);

  if (source_file.find('\'') != std::string::npos)
    return Status::FromErrorString(
        "Doesn't support single-quotes in filenames");

  // For zip .so file, src_file_spec will be "zip_path!/so_path".
  // Extract "zip_path" from the source_file.
  static constexpr llvm::StringLiteral k_zip_separator("!/");
  size_t pos = source_file.find(k_zip_separator);
  if (pos != std::string::npos)
    source_file.resize(pos);

  Status error;
  AdbClientUP adb(GetAdbClient(error));
  if (error.Fail())
    return error;

  // Use 'shell dd' to download the file slice with the offset and size.
  char cmd[PATH_MAX];
  snprintf(cmd, sizeof(cmd),
           "%sdd if='%s' iflag=skip_bytes,count_bytes "
           "skip=%" PRIu64 " count=%" PRIu64 " status=none",
           GetRunAs().c_str(), source_file.c_str(), src_offset, src_size);

  return adb->ShellToFile(cmd, minutes(1), dst_file_spec);
}

Status PlatformAndroid::DisconnectRemote() {
  Status error = PlatformLinux::DisconnectRemote();
  if (error.Success()) {
    m_device_id.clear();
    m_sdk_version = 0;
  }
  return error;
}

uint32_t PlatformAndroid::GetDefaultMemoryCacheLineSize() {
  return g_android_default_cache_size;
}

uint32_t PlatformAndroid::GetSdkVersion() {
  if (!IsConnected())
    return 0;

  if (m_sdk_version != 0)
    return m_sdk_version;

  std::string version_string;
  Status error;
  AdbClientUP adb(GetAdbClient(error));
  if (error.Fail())
    return 0;
  error =
      adb->Shell("getprop ro.build.version.sdk", seconds(5), &version_string);
  version_string = llvm::StringRef(version_string).trim().str();

  if (error.Fail() || version_string.empty()) {
    Log *log = GetLog(LLDBLog::Platform);
    LLDB_LOGF(log, "Get SDK version failed. (error: %s, output: %s)",
              error.AsCString(), version_string.c_str());
    return 0;
  }

  // FIXME: improve error handling
  llvm::to_integer(version_string, m_sdk_version);
  return m_sdk_version;
}

Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
                                           const FileSpec &dst_file_spec) {
  // For oat file we can try to fetch additional debug info from the device
  llvm::StringRef extension = module_sp->GetFileSpec().GetFileNameExtension();
  if (extension != ".oat" && extension != ".odex")
    return Status::FromErrorString(
        "Symbol file downloading only supported for oat and odex files");

  // If we have no information about the platform file we can't execute oatdump
  if (!module_sp->GetPlatformFileSpec())
    return Status::FromErrorString("No platform file specified");

  // Symbolizer isn't available before SDK version 23
  if (GetSdkVersion() < 23)
    return Status::FromErrorString(
        "Symbol file generation only supported on SDK 23+");

  // If we already have symtab then we don't have to try and generate one
  if (module_sp->GetSectionList()->FindSectionByName(".symtab") != nullptr)
    return Status::FromErrorString("Symtab already available in the module");

  Status error;
  AdbClientUP adb(GetAdbClient(error));
  if (error.Fail())
    return error;
  std::string tmpdir;
  error = adb->Shell("mktemp --directory --tmpdir /data/local/tmp", seconds(5),
                     &tmpdir);
  if (error.Fail() || tmpdir.empty())
    return Status::FromErrorStringWithFormat(
        "Failed to generate temporary directory on the device (%s)",
        error.AsCString());
  tmpdir = llvm::StringRef(tmpdir).trim().str();

  // Create file remover for the temporary directory created on the device
  std::unique_ptr<std::string, std::function<void(std::string *)>>
      tmpdir_remover(&tmpdir, [&adb](std::string *s) {
        StreamString command;
        command.Printf("rm -rf %s", s->c_str());
        Status error = adb->Shell(command.GetData(), seconds(5), nullptr);

        Log *log = GetLog(LLDBLog::Platform);
        if (log && error.Fail())
          LLDB_LOGF(log, "Failed to remove temp directory: %s",
                    error.AsCString());
      });

  FileSpec symfile_platform_filespec(tmpdir);
  symfile_platform_filespec.AppendPathComponent("symbolized.oat");

  // Execute oatdump on the remote device to generate a file with symtab
  StreamString command;
  command.Printf("oatdump --symbolize=%s --output=%s",
                 module_sp->GetPlatformFileSpec().GetPath(false).c_str(),
                 symfile_platform_filespec.GetPath(false).c_str());
  error = adb->Shell(command.GetData(), minutes(1), nullptr);
  if (error.Fail())
    return Status::FromErrorStringWithFormat("Oatdump failed: %s",
                                             error.AsCString());

  // Download the symbolfile from the remote device
  return GetFile(symfile_platform_filespec, dst_file_spec);
}

bool PlatformAndroid::GetRemoteOSVersion() {
  m_os_version = llvm::VersionTuple(GetSdkVersion());
  return !m_os_version.empty();
}

llvm::StringRef
PlatformAndroid::GetLibdlFunctionDeclarations(lldb_private::Process *process) {
  SymbolContextList matching_symbols;
  std::vector<const char *> dl_open_names = {"__dl_dlopen", "dlopen"};
  const char *dl_open_name = nullptr;
  Target &target = process->GetTarget();
  for (auto *name : dl_open_names) {
    target.GetImages().FindFunctionSymbols(
        ConstString(name), eFunctionNameTypeFull, matching_symbols);
    if (matching_symbols.GetSize()) {
      dl_open_name = name;
      break;
    }
  }
  // Older platform versions have the dl function symbols mangled
  if (dl_open_name == dl_open_names[0])
    return R"(
              extern "C" void* dlopen(const char*, int) asm("__dl_dlopen");
              extern "C" void* dlsym(void*, const char*) asm("__dl_dlsym");
              extern "C" int   dlclose(void*) asm("__dl_dlclose");
              extern "C" char* dlerror(void) asm("__dl_dlerror");
             )";

  return PlatformPOSIX::GetLibdlFunctionDeclarations(process);
}

PlatformAndroid::AdbClientUP PlatformAndroid::GetAdbClient(Status &error) {
  AdbClientUP adb = std::make_unique<AdbClient>(m_device_id);
  error = adb->Connect();
  return adb;
}

llvm::StringRef PlatformAndroid::GetPropertyPackageName() {
  return GetGlobalProperties().GetPropertyAtIndexAs<llvm::StringRef>(
      ePropertyPlatformPackageName, "");
}

std::string PlatformAndroid::GetRunAs() {
  llvm::StringRef run_as = GetPropertyPackageName();
  if (!run_as.empty()) {
    // When LLDB fails to pull file from a package directory due to security
    // constraint, user needs to set the package name to
    // 'platform.plugin.remote-android.package-name' property in order to run
    // shell commands as the package user using 'run-as' (e.g. to get file with
    // 'cat' and 'dd').
    // https://cs.android.com/android/platform/superproject/+/master:
    // system/core/run-as/run-as.cpp;l=39-61;
    // drc=4a77a84a55522a3b122f9c63ef0d0b8a6a131627
    return std::string("run-as '") + run_as.str() + "' ";
  }
  return run_as.str();
}

static bool NeedsCmdlineSupplement(const ProcessInstanceInfo &proc_info) {
  llvm::StringRef name = proc_info.GetExecutableFile().GetFilename();
  return name.contains("app_process") || name.contains("zygote");
}

// Fetch /proc/PID/cmdline for processes to get actual package names.
// Android apps often show as "zygote" or "app_process" without this.
static void SupplementWithCmdlineInfo(ProcessInstanceInfoList &proc_infos,
                                      AdbClient *adb) {
  if (proc_infos.empty())
    return;

  llvm::DenseMap<lldb::pid_t, ProcessInstanceInfo *> pid_map;
  std::string pid_list;
  for (auto &proc_info : proc_infos) {
    if (NeedsCmdlineSupplement(proc_info)) {
      lldb::pid_t pid = proc_info.GetProcessID();
      pid_map[pid] = &proc_info;
      if (!pid_list.empty())
        pid_list += " ";
      pid_list += std::to_string(pid);
    }
  }

  if (pid_list.empty())
    return;

  Log *log = GetLog(LLDBLog::Platform);

  // Use xargs -P to parallelize cmdline fetching (up to 8 concurrent reads)
  StreamString cmd;
  cmd.Printf(
      "echo '%s' | xargs -n 1 -P 8 sh -c "
      "'echo \"$1:$(cat /proc/$1/cmdline 2>/dev/null | tr \"\\0\" \" \")\"' sh",
      pid_list.c_str());

  std::string cmdline_output;
  Status error = adb->Shell(cmd.GetData(), seconds(5), &cmdline_output);

  if (error.Fail() || cmdline_output.empty())
    return;

  llvm::SmallVector<llvm::StringRef, 256> lines;
  llvm::StringRef(cmdline_output).split(lines, '\n', -1, false);

  for (llvm::StringRef line : lines) {
    line = line.trim();
    auto [pid_str, cmdline] = line.split(':');
    if (pid_str.empty() || cmdline.empty())
      continue;

    cmdline = cmdline.trim();

    lldb::pid_t pid;
    if (!llvm::to_integer(pid_str, pid) || cmdline.empty())
      continue;

    auto it = pid_map.find(pid);
    if (it == pid_map.end())
      continue;

    ProcessInstanceInfo *proc_info = it->second;
    llvm::SmallVector<llvm::StringRef, 16> args;
    cmdline.split(args, ' ', -1, false);

    if (!args.empty()) {
      proc_info->GetExecutableFile().SetFile(args[0], FileSpec::Style::posix);

      if (args.size() > 1) {
        Args process_args;
        for (size_t i = 1; i < args.size(); ++i) {
          if (!args[i].empty())
            process_args.AppendArgument(args[i]);
        }
        proc_info->SetArguments(process_args, false);
      }

      LLDB_LOGF(log,
                "PlatformAndroid::%s supplemented PID %llu with cmdline: %s",
                __FUNCTION__, static_cast<unsigned long long>(pid),
                cmdline.str().c_str());
    }
  }
}

uint32_t
PlatformAndroid::FindProcesses(const ProcessInstanceInfoMatch &match_info,
                               ProcessInstanceInfoList &proc_infos) {
  proc_infos.clear();

  if (IsHost())
    return PlatformLinux::FindProcesses(match_info, proc_infos);

  if (!m_remote_platform_sp)
    return 0;

  // Android-specific process name handling:
  // Apps spawned from zygote initially appear as "app_process" or "zygote"
  // in the process list, but their actual package names (e.g.,
  // "com.example.app") are only available in /proc/PID/cmdline. To support
  // name-based matching, we must first fetch cmdline info for all processes,
  // then apply the original name filter.
  ProcessInstanceInfoMatch broad_match_info = match_info;
  broad_match_info.SetNameMatchType(NameMatch::Ignore);

  ProcessInstanceInfoList all_procs;
  uint32_t count =
      m_remote_platform_sp->FindProcesses(broad_match_info, all_procs);

  if (count > 0) {
    Status error;
    AdbClientUP adb(GetAdbClient(error));
    if (error.Success())
      SupplementWithCmdlineInfo(all_procs, adb.get());

    // Apply the original name matching against supplemented process info.
    for (auto &proc_info : all_procs) {
      if (match_info.Matches(proc_info))
        proc_infos.push_back(proc_info);
    }
  }

  return proc_infos.size();
}

std::unique_ptr<AdbSyncService> PlatformAndroid::GetSyncService(Status &error) {
  auto sync_service = std::make_unique<AdbSyncService>(m_device_id);
  error = sync_service->SetupSyncConnection();
  if (error.Fail())
    return nullptr;
  return sync_service;
}
