/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/profiling/common/producer_support.h"

#include "perfetto/ext/base/android_utils.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_splitter.h"
#include "perfetto/tracing/core/data_source_config.h"
#include "src/traced/probes/packages_list/packages_list_parser.h"

namespace perfetto {
namespace profiling {

namespace {
base::Optional<Package> FindInPackagesList(
    uint64_t lookup_uid,
    const std::string& packages_list_path) {
  std::string content;
  if (!base::ReadFile(packages_list_path, &content)) {
    PERFETTO_ELOG("Failed to read %s", packages_list_path.c_str());
    return base::nullopt;
  }
  for (base::StringSplitter ss(std::move(content), '\n'); ss.Next();) {
    Package pkg;
    if (!ReadPackagesListLine(ss.cur_token(), &pkg)) {
      PERFETTO_ELOG("Failed to parse packages.list");
      return base::nullopt;
    }

    if (pkg.uid == lookup_uid) {
      return std::move(pkg);  // -Wreturn-std-move-in-c++11
    }
  }
  return base::nullopt;
}

bool AllPackagesProfileableByTrustedInitiator(
    const std::string& packages_list_path) {
  std::string content;
  if (!base::ReadFile(packages_list_path, &content)) {
    PERFETTO_ELOG("Failed to read %s", packages_list_path.c_str());
    return false;
  }
  bool ret = true;
  for (base::StringSplitter ss(std::move(content), '\n'); ss.Next();) {
    Package pkg;
    if (!ReadPackagesListLine(ss.cur_token(), &pkg)) {
      PERFETTO_ELOG("Failed to parse packages.list");
      return false;
    }

    ret = ret && (pkg.profileable || pkg.debuggable);
  }
  return ret;
}

}  // namespace

bool CanProfile(const DataSourceConfig& ds_config,
                uint64_t uid,
                const std::vector<std::string>& installed_by) {
// We restrict by !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) because a
// sideloaded heapprofd should not be restricted by this. Do note though that,
// at the moment, there isn't really a way to sideload a functioning heapprofd
// onto user builds.
#if !PERFETTO_BUILDFLAG(PERFETTO_ANDROID_BUILD) || \
    !PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  base::ignore_result(ds_config);
  base::ignore_result(uid);
  base::ignore_result(installed_by);
  return true;
#else
  std::string build_type = base::GetAndroidProp("ro.build.type");
  return CanProfileAndroid(ds_config, uid, installed_by, build_type,
                           "/data/system/packages.list");
#endif
}

bool CanProfileAndroid(const DataSourceConfig& ds_config,
                       uint64_t uid,
                       const std::vector<std::string>& installed_by,
                       const std::string& build_type,
                       const std::string& packages_list_path) {
  // These constants are replicated from libcutils android_filesystem_config.h,
  // to allow for building and testing the profilers outside the android tree.
  constexpr auto kAidSystem = 1000;           // AID_SYSTEM
  constexpr auto kAidUserOffset = 100000;     // AID_USER_OFFSET
  constexpr auto kAidAppStart = 10000;        // AID_APP_START
  constexpr auto kAidAppEnd = 19999;          // AID_APP_END
  constexpr auto kAidSdkSandboxStart = 20000; // AID_SDK_SANDBOX_PROCESS_START
  constexpr auto kAidSdkSandboxEnd = 29999;   // AID_SDK_SANDBOX_PROCESS_END
  constexpr auto kAidIsolatedStart = 90000;   // AID_ISOLATED_START
  constexpr auto kAidIsolatedEnd = 99999;     // AID_ISOLATED_END

  if (!build_type.empty() && build_type != "user") {
    return true;
  }

  // TODO(b/217368496): remove this.
  if (uid == kAidSystem) {
    return ds_config.session_initiator() ==
      DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM;
  }

  uint64_t uid_without_profile = uid % kAidUserOffset;
  uint64_t uid_for_lookup = 0;
  if (uid_without_profile >= kAidAppStart &&
      uid_without_profile <= kAidAppEnd) {
    // normal app
    uid_for_lookup = uid_without_profile;

  } else if (uid_without_profile >= kAidSdkSandboxStart &&
             uid_without_profile <= kAidSdkSandboxEnd) {
    // sdk sandbox process, has deterministic mapping to corresponding app
    uint64_t sdk_sandbox_offset = kAidSdkSandboxStart - kAidAppStart;
    uid_for_lookup = uid_without_profile - sdk_sandbox_offset;

  } else if (uid_without_profile >= kAidIsolatedStart &&
             uid_without_profile <= kAidIsolatedEnd) {
    // Isolated process. Such processes run under random UIDs and have no
    // straightforward link to the original app's UID without consulting
    // system_server. So we have to perform a very conservative check - if *all*
    // packages are profileable, then any isolated process must be profileable
    // as well, regardless of which package it's running for (which might not
    // even be the package in which the service was defined).
    // TODO(rsavitski): find a way for the platform to tell native services
    // about isolated<->app relations.
    bool trusted_initiator = ds_config.session_initiator() ==
                             DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM;
    return trusted_initiator &&
           AllPackagesProfileableByTrustedInitiator(packages_list_path);

  } else {
    // disallow everything else on release builds
    return false;
  }

  base::Optional<Package> pkg =
      FindInPackagesList(uid_for_lookup, packages_list_path);

  if (!pkg)
    return false;

  // check installer constraint if given
  if (!installed_by.empty()) {
    if (pkg->installed_by.empty()) {
      PERFETTO_ELOG("Cannot parse installer from packages.list");
      return false;
    }
    if (std::find(installed_by.cbegin(), installed_by.cend(),
                  pkg->installed_by) == installed_by.cend()) {
      // not installed by one of the requested origins
      return false;
    }
  }

  switch (ds_config.session_initiator()) {
    case DataSourceConfig::SESSION_INITIATOR_UNSPECIFIED:
      return pkg->profileable_from_shell || pkg->debuggable;
    case DataSourceConfig::SESSION_INITIATOR_TRUSTED_SYSTEM:
      return pkg->profileable || pkg->debuggable;
  }
  return false;
}

}  // namespace profiling
}  // namespace perfetto
