--- /dev/null
+cc_binary {
+ name: "android.hardware.memtrack-service.samsung-mali",
+ relative_install_path: "hw",
+ init_rc: ["memtrack.rc"],
+ vintf_fragments: ["memtrack.xml"],
+ vendor: true,
+ shared_libs: [
+ "android.hardware.memtrack-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "liblog",
+ ],
+ srcs: [
+ "Memtrack.cpp",
+ "GpuSysfsReader.cpp",
+ "filesystem.cpp",
+ "main.cpp",
+ ],
+}
--- /dev/null
+#include "GpuSysfsReader.h"
+
+#include <log/log.h>
+
+#include <fstream>
+#include <sstream>
+
+#include "filesystem.h"
+
+#undef LOG_TAG
+#define LOG_TAG "memtrack-gpusysfsreader"
+
+using namespace GpuSysfsReader;
+
+namespace {
+uint64_t readNode(const std::string node, pid_t pid) {
+ std::stringstream ss;
+ if (pid)
+ ss << kSysfsDevicePath << "/" << kProcessDir << "/" << pid << "/" << node;
+ else
+ ss << kSysfsDevicePath << "/" << node;
+ const std::string path = ss.str();
+
+ if (!filesystem::exists(filesystem::path(path))) {
+ ALOGV("File not found: %s", path.c_str());
+ return 0;
+ }
+
+ std::ifstream file(path.c_str());
+ if (!file.is_open()) {
+ ALOGW("Failed to open %s path", path.c_str());
+ return 0;
+ }
+
+ uint64_t out;
+ file >> out;
+ file.close();
+
+ return out;
+}
+} // namespace
+
+uint64_t GpuSysfsReader::getDmaBufGpuMem(pid_t pid) { return readNode(kDmaBufGpuMemNode, pid); }
+
+uint64_t GpuSysfsReader::getGpuMemTotal(pid_t pid) { return readNode(kTotalGpuMemNode, pid); }
+
+uint64_t GpuSysfsReader::getPrivateGpuMem(pid_t pid) {
+ auto dma_buf_size = getDmaBufGpuMem(pid);
+ auto gpu_total_size = getGpuMemTotal(pid);
+
+ if (dma_buf_size > gpu_total_size) {
+ ALOGE("Bug in reader, dma-buf size (%" PRIu64 ") is higher than total gpu size (%" PRIu64
+ ")",
+ dma_buf_size, gpu_total_size);
+ return 0;
+ }
+
+ return gpu_total_size - dma_buf_size;
+}
--- /dev/null
+
+#pragma once
+
+#include <inttypes.h>
+#include <sys/types.h>
+
+namespace GpuSysfsReader {
+uint64_t getDmaBufGpuMem(pid_t pid = 0);
+uint64_t getGpuMemTotal(pid_t pid = 0);
+uint64_t getPrivateGpuMem(pid_t pid = 0);
+
+constexpr char kSysfsDevicePath[] = "/sys/class/misc/mali0/device";
+constexpr char kProcessDir[] = "kprcs";
+constexpr char kMappedDmaBufsDir[] = "dma_bufs";
+constexpr char kTotalGpuMemNode[] = "total_gpu_mem";
+constexpr char kDmaBufGpuMemNode[] = "dma_buf_gpu_mem";
+} // namespace GpuSysfsReader
--- /dev/null
+#include <Memtrack.h>
+#include <stdlib.h>
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "GpuSysfsReader.h"
+#include "filesystem.h"
+
+#undef LOG_TAG
+#define LOG_TAG "memtrack-core"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+ndk::ScopedAStatus Memtrack::getMemory(int pid, MemtrackType type,
+ std::vector<MemtrackRecord>* _aidl_return) {
+ if (pid < 0)
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
+
+ if (type != MemtrackType::OTHER && type != MemtrackType::GL && type != MemtrackType::GRAPHICS &&
+ type != MemtrackType::MULTIMEDIA && type != MemtrackType::CAMERA)
+ return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
+
+ _aidl_return->clear();
+
+ // Other types are retained only for backward compatibility
+ if (type != MemtrackType::GL && type != MemtrackType::GRAPHICS)
+ return ndk::ScopedAStatus::ok();
+
+ // pid 0 is only supported for GL type to report total private memory
+ if (pid == 0 && type != MemtrackType::GL)
+ return ndk::ScopedAStatus::ok();
+
+ uint64_t size = 0;
+ switch (type) {
+ case MemtrackType::GL:
+ size = GpuSysfsReader::getPrivateGpuMem(pid);
+ break;
+ case MemtrackType::GRAPHICS:
+ // TODO(b/194483693): This is not PSS as required by memtrack HAL
+ // but complete dmabuf allocations. Reporting PSS requires reading
+ // procfs. This HAL does not have that permission yet.
+ size = GpuSysfsReader::getDmaBufGpuMem(pid);
+ break;
+ default:
+ break;
+ }
+
+ MemtrackRecord record = {
+ .flags = MemtrackRecord::FLAG_SMAPS_UNACCOUNTED,
+ .sizeInBytes = static_cast<long>(size),
+ };
+ _aidl_return->emplace_back(record);
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Memtrack::getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) {
+ auto devPath = filesystem::path(GpuSysfsReader::kSysfsDevicePath);
+ std::string devName = "default-gpu";
+ if (filesystem::exists(devPath) && filesystem::is_symlink(devPath)) {
+ devName = filesystem::read_symlink(devPath).filename().string();
+ }
+
+ DeviceInfo dev_info = {.id = 0, .name = devName};
+
+ _aidl_return->clear();
+ _aidl_return->emplace_back(dev_info);
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace memtrack
+} // namespace hardware
+} // namespace android
+} // namespace aidl
--- /dev/null
+
+#pragma once
+
+#include <aidl/android/hardware/memtrack/BnMemtrack.h>
+#include <aidl/android/hardware/memtrack/DeviceInfo.h>
+#include <aidl/android/hardware/memtrack/MemtrackRecord.h>
+#include <aidl/android/hardware/memtrack/MemtrackType.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace memtrack {
+
+class Memtrack : public BnMemtrack {
+public:
+ ndk::ScopedAStatus getMemory(int pid, MemtrackType type,
+ std::vector<MemtrackRecord>* _aidl_return) override;
+
+ ndk::ScopedAStatus getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) override;
+};
+
+} // namespace memtrack
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+++ /dev/null
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_library_shared {
- name: "libmemtrack-pixel",
- vendor: true,
- srcs: [
- "Memtrack.cpp",
- "GpuSysfsReader.cpp",
- "filesystem.cpp",
- ],
- export_include_dirs: [
- "include",
- ],
- shared_libs: [
- "android.hardware.memtrack-V1-ndk",
- "libbase",
- "libbinder_ndk",
- "liblog",
- ],
- cppflags: [
- "-Wall",
- "-Werror",
- "-Wformat",
- "-Wthread-safety",
- "-Wunused",
- "-Wunreachable-code",
- ],
- visibility: [
- "//hardware/google/graphics/common/memtrack-pixel/service:__pkg__"
- ],
-}
+++ /dev/null
-#include "GpuSysfsReader.h"
-
-#include <log/log.h>
-
-#include <fstream>
-#include <sstream>
-
-#include "filesystem.h"
-
-#undef LOG_TAG
-#define LOG_TAG "memtrack-gpusysfsreader"
-
-using namespace GpuSysfsReader;
-
-namespace {
-uint64_t readNode(const std::string node, pid_t pid) {
- std::stringstream ss;
- if (pid)
- ss << kSysfsDevicePath << "/" << kProcessDir << "/" << pid << "/" << node;
- else
- ss << kSysfsDevicePath << "/" << node;
- const std::string path = ss.str();
-
- if (!filesystem::exists(filesystem::path(path))) {
- ALOGV("File not found: %s", path.c_str());
- return 0;
- }
-
- std::ifstream file(path.c_str());
- if (!file.is_open()) {
- ALOGW("Failed to open %s path", path.c_str());
- return 0;
- }
-
- uint64_t out;
- file >> out;
- file.close();
-
- return out;
-}
-} // namespace
-
-uint64_t GpuSysfsReader::getDmaBufGpuMem(pid_t pid) { return readNode(kDmaBufGpuMemNode, pid); }
-
-uint64_t GpuSysfsReader::getGpuMemTotal(pid_t pid) { return readNode(kTotalGpuMemNode, pid); }
-
-uint64_t GpuSysfsReader::getPrivateGpuMem(pid_t pid) {
- auto dma_buf_size = getDmaBufGpuMem(pid);
- auto gpu_total_size = getGpuMemTotal(pid);
-
- if (dma_buf_size > gpu_total_size) {
- ALOGE("Bug in reader, dma-buf size (%" PRIu64 ") is higher than total gpu size (%" PRIu64
- ")",
- dma_buf_size, gpu_total_size);
- return 0;
- }
-
- return gpu_total_size - dma_buf_size;
-}
+++ /dev/null
-
-#pragma once
-
-#include <inttypes.h>
-#include <sys/types.h>
-
-namespace GpuSysfsReader {
-uint64_t getDmaBufGpuMem(pid_t pid = 0);
-uint64_t getGpuMemTotal(pid_t pid = 0);
-uint64_t getPrivateGpuMem(pid_t pid = 0);
-
-constexpr char kSysfsDevicePath[] = "/sys/class/misc/mali0/device";
-constexpr char kProcessDir[] = "kprcs";
-constexpr char kMappedDmaBufsDir[] = "dma_bufs";
-constexpr char kTotalGpuMemNode[] = "total_gpu_mem";
-constexpr char kDmaBufGpuMemNode[] = "dma_buf_gpu_mem";
-} // namespace GpuSysfsReader
+++ /dev/null
-#include <Memtrack.h>
-#include <stdlib.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "GpuSysfsReader.h"
-#include "filesystem.h"
-
-#undef LOG_TAG
-#define LOG_TAG "memtrack-core"
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace memtrack {
-
-ndk::ScopedAStatus Memtrack::getMemory(int pid, MemtrackType type,
- std::vector<MemtrackRecord>* _aidl_return) {
- if (pid < 0)
- return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_ILLEGAL_ARGUMENT));
-
- if (type != MemtrackType::OTHER && type != MemtrackType::GL && type != MemtrackType::GRAPHICS &&
- type != MemtrackType::MULTIMEDIA && type != MemtrackType::CAMERA)
- return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
-
- _aidl_return->clear();
-
- // Other types are retained only for backward compatibility
- if (type != MemtrackType::GL && type != MemtrackType::GRAPHICS)
- return ndk::ScopedAStatus::ok();
-
- // pid 0 is only supported for GL type to report total private memory
- if (pid == 0 && type != MemtrackType::GL)
- return ndk::ScopedAStatus::ok();
-
- uint64_t size = 0;
- switch (type) {
- case MemtrackType::GL:
- size = GpuSysfsReader::getPrivateGpuMem(pid);
- break;
- case MemtrackType::GRAPHICS:
- // TODO(b/194483693): This is not PSS as required by memtrack HAL
- // but complete dmabuf allocations. Reporting PSS requires reading
- // procfs. This HAL does not have that permission yet.
- size = GpuSysfsReader::getDmaBufGpuMem(pid);
- break;
- default:
- break;
- }
-
- MemtrackRecord record = {
- .flags = MemtrackRecord::FLAG_SMAPS_UNACCOUNTED,
- .sizeInBytes = static_cast<long>(size),
- };
- _aidl_return->emplace_back(record);
-
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Memtrack::getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) {
- auto devPath = filesystem::path(GpuSysfsReader::kSysfsDevicePath);
- std::string devName = "default-gpu";
- if (filesystem::exists(devPath) && filesystem::is_symlink(devPath)) {
- devName = filesystem::read_symlink(devPath).filename().string();
- }
-
- DeviceInfo dev_info = {.id = 0, .name = devName};
-
- _aidl_return->clear();
- _aidl_return->emplace_back(dev_info);
- return ndk::ScopedAStatus::ok();
-}
-
-} // namespace memtrack
-} // namespace hardware
-} // namespace android
-} // namespace aidl
+++ /dev/null
-#include "filesystem.h"
-
-#include <dirent.h>
-#include <log/log.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-namespace filesystem {
-
-bool exists(const path& p) {
- struct stat s;
- return stat(p.string().c_str(), &s) == 0;
-}
-
-bool is_directory(const path& p) {
- struct stat s;
- if (stat(p.string().c_str(), &s))
- return false;
-
- return S_ISDIR(s.st_mode);
-}
-
-bool is_symlink(const path& p) {
- struct stat s;
- if (lstat(p.string().c_str(), &s))
- return false;
-
- return S_ISLNK(s.st_mode);
-}
-
-path read_symlink(const path& p) {
- char* actualPath = realpath(p.string().c_str(), NULL);
- if (!actualPath) {
- return path(p.string());
- }
-
- path out(actualPath);
- free(actualPath);
- return out;
-}
-
-std::vector<directory_entry> directory_iterator(const path& p) {
- if (!exists(p) || !is_directory(p))
- return {};
-
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(p.string().c_str()), &closedir);
- if (!dir) {
- ALOGE("Failed to open %s directory", p.string().c_str());
- }
-
- std::vector<directory_entry> out;
- struct dirent* dent;
- while ((dent = readdir(dir.get()))) {
- if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
- continue;
-
- std::stringstream ss(p.string());
- ss << "/" << dent->d_name;
- out.emplace_back(ss.str());
- }
-
- return out;
-}
-
-} // namespace filesystem
+++ /dev/null
-// TODO(b/147469372): filesystem library in Android's libcxx is not available
-// for vendors. It had an unstable ABI and libcxx isn't updated ever since.
-
-// This simply implements some of the required functions in not-so-safe fashion.
-
-#pragma once
-
-#include <dirent.h>
-#include <log/log.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <string>
-#include <vector>
-
-namespace filesystem {
-class path {
-public:
- path(const std::string _path) : strPath(_path) {}
-
- path filename() const {
- auto pos = strPath.rfind('/');
- if (pos == std::string::npos)
- return path(strPath);
-
- pos++;
- auto l = strPath.size();
- return path(strPath.substr(pos, l - pos));
- }
-
- std::string string() const { return strPath; }
-
-private:
- std::string strPath;
-};
-
-class directory_entry {
-public:
- directory_entry(const std::string _path) : p(_path) {}
-
- class path path() {
- return p;
- }
-
-private:
- class path p;
-};
-
-bool exists(const path& p);
-
-bool is_directory(const path& p);
-
-bool is_symlink(const path& p);
-
-path read_symlink(const path& p);
-
-// Vector is easier to create than an iterator and serves our purposes well
-std::vector<directory_entry> directory_iterator(const path& p);
-} // namespace filesystem
+++ /dev/null
-
-#pragma once
-
-#include <aidl/android/hardware/memtrack/BnMemtrack.h>
-#include <aidl/android/hardware/memtrack/DeviceInfo.h>
-#include <aidl/android/hardware/memtrack/MemtrackRecord.h>
-#include <aidl/android/hardware/memtrack/MemtrackType.h>
-
-namespace aidl {
-namespace android {
-namespace hardware {
-namespace memtrack {
-
-class Memtrack : public BnMemtrack {
-public:
- ndk::ScopedAStatus getMemory(int pid, MemtrackType type,
- std::vector<MemtrackRecord>* _aidl_return) override;
-
- ndk::ScopedAStatus getGpuDeviceInfo(std::vector<DeviceInfo>* _aidl_return) override;
-};
-
-} // namespace memtrack
-} // namespace hardware
-} // namespace android
-} // namespace aidl
--- /dev/null
+#include "filesystem.h"
+
+#include <dirent.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace filesystem {
+
+bool exists(const path& p) {
+ struct stat s;
+ return stat(p.string().c_str(), &s) == 0;
+}
+
+bool is_directory(const path& p) {
+ struct stat s;
+ if (stat(p.string().c_str(), &s))
+ return false;
+
+ return S_ISDIR(s.st_mode);
+}
+
+bool is_symlink(const path& p) {
+ struct stat s;
+ if (lstat(p.string().c_str(), &s))
+ return false;
+
+ return S_ISLNK(s.st_mode);
+}
+
+path read_symlink(const path& p) {
+ char* actualPath = realpath(p.string().c_str(), NULL);
+ if (!actualPath) {
+ return path(p.string());
+ }
+
+ path out(actualPath);
+ free(actualPath);
+ return out;
+}
+
+std::vector<directory_entry> directory_iterator(const path& p) {
+ if (!exists(p) || !is_directory(p))
+ return {};
+
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(p.string().c_str()), &closedir);
+ if (!dir) {
+ ALOGE("Failed to open %s directory", p.string().c_str());
+ }
+
+ std::vector<directory_entry> out;
+ struct dirent* dent;
+ while ((dent = readdir(dir.get()))) {
+ if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
+ continue;
+
+ std::stringstream ss(p.string());
+ ss << "/" << dent->d_name;
+ out.emplace_back(ss.str());
+ }
+
+ return out;
+}
+
+} // namespace filesystem
--- /dev/null
+// TODO(b/147469372): filesystem library in Android's libcxx is not available
+// for vendors. It had an unstable ABI and libcxx isn't updated ever since.
+
+// This simply implements some of the required functions in not-so-safe fashion.
+
+#pragma once
+
+#include <dirent.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+
+namespace filesystem {
+class path {
+public:
+ path(const std::string _path) : strPath(_path) {}
+
+ path filename() const {
+ auto pos = strPath.rfind('/');
+ if (pos == std::string::npos)
+ return path(strPath);
+
+ pos++;
+ auto l = strPath.size();
+ return path(strPath.substr(pos, l - pos));
+ }
+
+ std::string string() const { return strPath; }
+
+private:
+ std::string strPath;
+};
+
+class directory_entry {
+public:
+ directory_entry(const std::string _path) : p(_path) {}
+
+ class path path() {
+ return p;
+ }
+
+private:
+ class path p;
+};
+
+bool exists(const path& p);
+
+bool is_directory(const path& p);
+
+bool is_symlink(const path& p);
+
+path read_symlink(const path& p);
+
+// Vector is easier to create than an iterator and serves our purposes well
+std::vector<directory_entry> directory_iterator(const path& p);
+} // namespace filesystem
--- /dev/null
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "Memtrack.h"
+
+#undef LOG_TAG
+#define LOG_TAG "memtrack-service"
+
+using aidl::android::hardware::memtrack::Memtrack;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ std::shared_ptr<Memtrack> memtrack = ndk::SharedRefBase::make<Memtrack>();
+
+ const std::string instance = std::string() + Memtrack::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(memtrack->asBinder().get(), instance.c_str());
+ CHECK(status == STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // Unreachable
+}
--- /dev/null
+service vendor.memtrack-default /vendor/bin/hw/android.hardware.memtrack-service.samsung-mali
+ class hal
+ user graphics
+ group system
--- /dev/null
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.memtrack</name>
+ <fqname>IMemtrack/default</fqname>
+ </hal>
+</manifest>
+
+++ /dev/null
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "android.hardware.memtrack-service.pixel",
- relative_install_path: "hw",
- init_rc: ["memtrack.rc"],
- vintf_fragments: ["memtrack.xml"],
- vendor: true,
- shared_libs: [
- "android.hardware.memtrack-V1-ndk",
- "libbase",
- "libbinder_ndk",
- "libmemtrack-pixel",
- ],
- srcs: [
- "main.cpp",
- ],
-}
+++ /dev/null
-#include <Memtrack.h>
-#include <android-base/logging.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
-#undef LOG_TAG
-#define LOG_TAG "memtrack-service"
-
-using aidl::android::hardware::memtrack::Memtrack;
-
-int main() {
- ABinderProcess_setThreadPoolMaxThreadCount(0);
- std::shared_ptr<Memtrack> memtrack = ndk::SharedRefBase::make<Memtrack>();
-
- const std::string instance = std::string() + Memtrack::descriptor + "/default";
- binder_status_t status =
- AServiceManager_addService(memtrack->asBinder().get(), instance.c_str());
- CHECK(status == STATUS_OK);
-
- ABinderProcess_joinThreadPool();
- return EXIT_FAILURE; // Unreachable
-}
+++ /dev/null
-service vendor.memtrack-default /vendor/bin/hw/android.hardware.memtrack-service.pixel
- class hal
- user graphics
- group system
+++ /dev/null
-<manifest version="1.0" type="device">
- <hal format="aidl">
- <name>android.hardware.memtrack</name>
- <fqname>IMemtrack/default</fqname>
- </hal>
-</manifest>
-