/*
 * 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/trace_processor/importers/proto/profiler_util.h"
#include <optional>

#include "perfetto/ext/base/string_utils.h"
#include "src/trace_processor/storage/trace_storage.h"

namespace perfetto {
namespace trace_processor {
namespace {

// Try to extract the package name from a path like:
// * /data/app/[packageName]-[randomString]/base.apk
// * /data/app/~~[randomStringA]/[packageName]-[randomStringB]/base.apk
// The latter is newer (R+), and was added to avoid leaking package names via
// mountinfo of incremental apk mounts.
std::optional<base::StringView> PackageFromApp(base::StringView location) {
  location = location.substr(base::StringView("/data/app/").size());
  size_t start = 0;
  if (location.at(0) == '~') {
    size_t slash = location.find('/');
    if (slash == base::StringView::npos) {
      return std::nullopt;
    }
    start = slash + 1;
  }
  size_t end = location.find('/', start + 1);
  if (end == base::StringView::npos) {
    return std::nullopt;
  }
  location = location.substr(start, end);
  size_t minus = location.find('-');
  if (minus == base::StringView::npos) {
    return std::nullopt;
  }
  return location.substr(0, minus);
}

}  // namespace

std::optional<std::string> PackageFromLocation(TraceStorage* storage,
                                               base::StringView location) {
  // List of some hardcoded apps that do not follow the scheme used in
  // PackageFromApp. Ask for yours to be added.
  //
  // TODO(b/153632336): Get rid of the hardcoded list of system apps.
  base::StringView sysui(
      "/system_ext/priv-app/SystemUIGoogle/SystemUIGoogle.apk");
  if (location.size() >= sysui.size() &&
      location.substr(0, sysui.size()) == sysui) {
    return "com.android.systemui";
  }

  base::StringView phonesky("/product/priv-app/Phonesky/Phonesky.apk");
  if (location.size() >= phonesky.size() &&
      location.substr(0, phonesky.size()) == phonesky) {
    return "com.android.vending";
  }

  base::StringView maps("/product/app/Maps/Maps.apk");
  if (location.size() >= maps.size() &&
      location.substr(0, maps.size()) == maps) {
    return "com.google.android.apps.maps";
  }

  base::StringView launcher(
      "/system_ext/priv-app/NexusLauncherRelease/NexusLauncherRelease.apk");
  if (location.size() >= launcher.size() &&
      location.substr(0, launcher.size()) == launcher) {
    return "com.google.android.apps.nexuslauncher";
  }

  base::StringView photos("/product/app/Photos/Photos.apk");
  if (location.size() >= photos.size() &&
      location.substr(0, photos.size()) == photos) {
    return "com.google.android.apps.photos";
  }

  base::StringView wellbeing(
      "/product/priv-app/WellbeingPrebuilt/WellbeingPrebuilt.apk");
  if (location.size() >= wellbeing.size() &&
      location.substr(0, wellbeing.size()) == wellbeing) {
    return "com.google.android.apps.wellbeing";
  }

  if (location.find("DevicePersonalizationPrebuilt") !=
          base::StringView::npos ||
      location.find("MatchMaker") != base::StringView::npos) {
    return "com.google.android.as";
  }

  if (location.find("DeviceIntelligenceNetworkPrebuilt") !=
      base::StringView::npos) {
    return "com.google.android.as.oss";
  }

  if (location.find("SettingsIntelligenceGooglePrebuilt") !=
      base::StringView::npos) {
    return "com.google.android.settings.intelligence";
  }

  base::StringView gm("/product/app/PrebuiltGmail/PrebuiltGmail.apk");
  if (location.size() >= gm.size() && location.substr(0, gm.size()) == gm) {
    return "com.google.android.gm";
  }

  if (location.find("PrebuiltGmsCore") != base::StringView::npos ||
      location.find("com.google.android.gms") != base::StringView::npos) {
    return "com.google.android.gms";
  }

  base::StringView velvet("/product/priv-app/Velvet/Velvet.apk");
  if (location.size() >= velvet.size() &&
      location.substr(0, velvet.size()) == velvet) {
    return "com.google.android.googlequicksearchbox";
  }

  base::StringView inputmethod(
      "/product/app/LatinIMEGooglePrebuilt/LatinIMEGooglePrebuilt.apk");
  if (location.size() >= inputmethod.size() &&
      location.substr(0, inputmethod.size()) == inputmethod) {
    return "com.google.android.inputmethod.latin";
  }

  base::StringView messaging("/product/app/PrebuiltBugle/PrebuiltBugle.apk");
  if (location.size() >= messaging.size() &&
      location.substr(0, messaging.size()) == messaging) {
    return "com.google.android.apps.messaging";
  }

  // Deal with paths to /data/app/...

  auto extract_package =
      [storage](base::StringView path) -> std::optional<std::string> {
    auto package = PackageFromApp(path);
    if (!package) {
      PERFETTO_DLOG("Failed to parse %s", path.ToStdString().c_str());
      storage->IncrementStats(stats::deobfuscate_location_parse_error);
      return std::nullopt;
    }
    return package->ToStdString();
  };

  base::StringView data_app("/data/app/");
  size_t data_app_sz = data_app.size();
  if (location.substr(0, data_app.size()) == data_app) {
    return extract_package(location);
  }

  // Check for in-memory decompressed dexfile, example prefixes:
  // * "[anon:dalvik-classes.dex extracted in memory from"
  // * "/dev/ashmem/dalvik-classes.dex extracted in memory from"
  // The latter form is for older devices (Android P and before).
  // We cannot hardcode the filename since it could be for example
  // "classes2.dex" for multidex apks.
  base::StringView inmem_dex("dex extracted in memory from /data/app/");
  size_t match_pos = location.find(inmem_dex);
  if (match_pos != base::StringView::npos) {
    auto data_app_path =
        location.substr(match_pos + inmem_dex.size() - data_app_sz);
    return extract_package(data_app_path);
  }

  return std::nullopt;
}

std::string FullyQualifiedDeobfuscatedName(
    protos::pbzero::ObfuscatedClass::Decoder& cls,
    protos::pbzero::ObfuscatedMember::Decoder& member) {
  std::string member_deobfuscated_name =
      member.deobfuscated_name().ToStdString();
  if (base::Contains(member_deobfuscated_name, '.')) {
    // Fully qualified name.
    return member_deobfuscated_name;
  } else {
    // Name relative to class.
    return cls.deobfuscated_name().ToStdString() + "." +
           member_deobfuscated_name;
  }
}

}  // namespace trace_processor
}  // namespace perfetto
