Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/tools/profiler/core/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 5 kB image not shown  

Quelle  PowerCounters-android.cpp   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "PowerCounters.h"
#include "nsXULAppAPI.h"  // for XRE_IsParentProcess
#include <dlfcn.h>

#define ALOG(args...) \
  __android_log_print(ANDROID_LOG_INFO, "GeckoProfiler"##args)

/*
 * The following declarations come from the dlext.h header (not in the ndk).
 * https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/include/android/dlext.h;drc=655e430b28d7404f763e7ebefe84fba5a387666d
 */

struct android_namespace_t;
typedef struct {
  /** A bitmask of `ANDROID_DLEXT_` enum values. */
  uint64_t flags;

  /** Used by `ANDROID_DLEXT_RESERVED_ADDRESS` and
   * `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`. */

  void* _Nullable reserved_addr;
  /** Used by `ANDROID_DLEXT_RESERVED_ADDRESS` and
   * `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`. */

  size_t reserved_size;

  /** Used by `ANDROID_DLEXT_WRITE_RELRO` and `ANDROID_DLEXT_USE_RELRO`. */
  int relro_fd;

  /** Used by `ANDROID_DLEXT_USE_LIBRARY_FD`. */
  int library_fd;
  /** Used by `ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET` */
  off64_t library_fd_offset;

  /** Used by `ANDROID_DLEXT_USE_NAMESPACE`. */
  struct android_namespace_t* _Nullable library_namespace;
} android_dlextinfo;
enum { ANDROID_DLEXT_USE_NAMESPACE = 0x200 };
extern "C"
    __attribute__((visibility("default"))) void* _Nullable android_dlopen_ext(
        const char* _Nullable __filename, int __flags,
        const android_dlextinfo* _Nullable __info);

// See also documentation at
// https://developer.android.com/studio/profile/power-profiler#power-rails
bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr);

class RailEnergy final : public BaseProfilerCount {
 public:
  explicit RailEnergy(RailEnergyData* data, const char* aRailName,
                      const char* aSubsystemName)
      : BaseProfilerCount(aSubsystemName, "power", aRailName),
        mDataPtr(data),
        mLastTimestamp(0) {}

  ~RailEnergy() {}

  RailEnergy(const RailEnergy&) = delete;
  RailEnergy& operator=(const RailEnergy&) = delete;

  CountSample Sample() override {
    CountSample result = {
        // RailEnergyData.energy is in microwatt-seconds (uWs)
        // we need to return values in picowatt-hour.
        .count = static_cast<int64_t>(mDataPtr->energy * 1e3 / 3.6),
        .number = 0,
        .isSampleNew = mDataPtr->timestamp != mLastTimestamp,
    };
    mLastTimestamp = mDataPtr->timestamp;
    return result;
  }

 private:
  RailEnergyData* mDataPtr;
  uint64_t mLastTimestamp;
};

PowerCounters::PowerCounters() {
  if (!XRE_IsParentProcess()) {
    // Energy meters are global, so only sample them on the parent.
    return;
  }

  // A direct dlopen call on libperfetto_android_internal.so fails with a
  // namespace error because libperfetto_android_internal.so is missing in
  // /etc/public.libraries.txt
  // Instead, use android_dlopen_ext with the "default" namespace.
  void* libcHandle = dlopen("libc.so", RTLD_LAZY);
  if (!libcHandle) {
    ALOG("failed to dlopen libc: %s", dlerror());
    return;
  }

  struct android_namespace_t* (*android_get_exported_namespace)(const char*) =
      reinterpret_cast<struct android_namespace_t* (*)(const char*)>(
          dlsym(libcHandle, "__loader_android_get_exported_namespace"));
  if (!android_get_exported_namespace) {
    ALOG("failed to get __loader_android_get_exported_namespace: %s",
         dlerror());
    return;
  }

  struct android_namespace_t* ns = android_get_exported_namespace("default");
  const android_dlextinfo dlextinfo = {
      .flags = ANDROID_DLEXT_USE_NAMESPACE,
      .library_namespace = ns,
  };

  mLibperfettoModule = android_dlopen_ext("libperfetto_android_internal.so",
                                          RTLD_LOCAL | RTLD_LAZY, &dlextinfo);
  MOZ_ASSERT(mLibperfettoModule);
  if (!mLibperfettoModule) {
    ALOG("failed to get libperfetto handle: %s", dlerror());
    return;
  }

  decltype(&GetAvailableRails) getAvailableRails =
      reinterpret_cast<decltype(&GetAvailableRails)>(
          dlsym(mLibperfettoModule, "GetAvailableRails"));
  if (!getAvailableRails) {
    ALOG("failed to get GetAvailableRails pointer: %s", dlerror());
    return;
  }

  constexpr size_t kMaxNumRails = 32;
  if (!mRailDescriptors.resize(kMaxNumRails)) {
    ALOG("failed to grow mRailDescriptors");
    return;
  }
  size_t numRails = mRailDescriptors.length();
  getAvailableRails(&mRailDescriptors[0], &numRails);
  mRailDescriptors.shrinkTo(numRails);
  ALOG("found %zu rails", numRails);
  if (numRails == 0) {
    // We will see 0 rails either if the device has no support for power
    // profiling or if the SELinux policy blocks access (ie. on a non-rooted
    // device).
    return;
  }

  if (!mRailEnergyData.resize(numRails)) {
    ALOG("failed to grow mRailEnergyData");
    return;
  }
  for (size_t i = 0; i < numRails; ++i) {
    RailDescriptor& rail = mRailDescriptors[i];
    ALOG("rail %zu, name: %s, subsystem: %s", i, rail.rail_name,
         rail.subsys_name);
    RailEnergy* railEnergy =
        new RailEnergy(&mRailEnergyData[i], rail.rail_name, rail.subsys_name);
    if (!mCounters.emplaceBack(railEnergy)) {
      delete railEnergy;
    }
  }

  mGetRailEnergyData = reinterpret_cast<decltype(&GetRailEnergyData)>(
      dlsym(mLibperfettoModule, "GetRailEnergyData"));
  if (!mGetRailEnergyData) {
    ALOG("failed to get GetRailEnergyData pointer");
    return;
  }
}
PowerCounters::~PowerCounters() {
  if (mLibperfettoModule) {
    dlclose(mLibperfettoModule);
  }
}
void PowerCounters::Sample() {
  // Energy meters are global, so only sample them on the parent.
  // Also return early if we failed to access the GetRailEnergyData symbol.
  if (!XRE_IsParentProcess() || !mGetRailEnergyData) {
    return;
  }

  size_t length = mRailEnergyData.length();
  mGetRailEnergyData(&mRailEnergyData[0], &length);
}

98%


¤ Dauer der Verarbeitung: 0.28 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.