From hardware/google/graphics/common @ android-13.0.0_r4 Needs:urubinoaa30f47cf6
ced6904b88
620019f26c
Change-Id: I46ebd21033b7b387503adc835a5d6057bc7c8779
parent
f302a32df3
commit
1ce96deebe
@ -0,0 +1,34 @@ |
|||||||
|
|
||||||
|
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__" |
||||||
|
], |
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
#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; |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
|
||||||
|
#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
|
@ -0,0 +1,79 @@ |
|||||||
|
#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
|
@ -0,0 +1,70 @@ |
|||||||
|
#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
|
@ -0,0 +1,60 @@ |
|||||||
|
// 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
|
@ -0,0 +1,25 @@ |
|||||||
|
|
||||||
|
#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
|
@ -0,0 +1,20 @@ |
|||||||
|
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", |
||||||
|
], |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
#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
|
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
service vendor.memtrack-default /vendor/bin/hw/android.hardware.memtrack-service.pixel |
||||||
|
class hal |
||||||
|
user graphics |
||||||
|
group system |
@ -0,0 +1,7 @@ |
|||||||
|
<manifest version="1.0" type="device"> |
||||||
|
<hal format="aidl"> |
||||||
|
<name>android.hardware.memtrack</name> |
||||||
|
<fqname>IMemtrack/default</fqname> |
||||||
|
</hal> |
||||||
|
</manifest> |
||||||
|
|
Loading…
Reference in new issue