From: Caisking Date: Wed, 24 Sep 2025 08:51:04 +0000 (+0800) Subject: 增加内存管理接口 X-Git-Tag: V1.0.9_20251128_194606_LN~333 X-Git-Url: http://git.snicker.com.cn/css/static/gitweb.css?a=commitdiff_plain;h=a1226458128895a5aad2804a488447d1158d6473;p=mirrors%2FFD230.git 增加内存管理接口 --- diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/system/include/MemoryManager.h b/code/sdk/application/wearable/ln/nativeapp/nativeui/system/include/MemoryManager.h new file mode 100644 index 000000000..01d4a9471 --- /dev/null +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/system/include/MemoryManager.h @@ -0,0 +1,149 @@ +/* + * @Author: Assistant + * @Date: 2024-12-19 + * @Description: Memory Manager - 内存管理模块,用于OTA和表情文件下载时的内存检查 + */ +#ifndef MEMORY_MANAGER_H +#define MEMORY_MANAGER_H + +#include +#include +#include + +namespace OHOS +{ + /* + 4个文件夹 + 默认文件:user/res/ + 系统文件:user/system/ + 用户数据:user/userdata/ + 更新文件:user/update/ + */ + #define DEFAULT_RES_PATH "/user/res/" + #define DEFAULT_SYSTEM_PATH "/user/system/" + #define DEFAULT_USERDATA_PATH "/user/userdata/" + #define DEFAULT_UPDATE_PATH "/user/update/" + + /** + * @brief 内存管理类 + * @details 用于OTA和表情文件下载时的内存检查和管理 + */ + class MemoryManager + { + public: + /** + * @brief 获取MemoryManager单例实例 + * @return MemoryManager* 单例实例指针 + */ + static MemoryManager *GetInstance(); + + /** + * @brief 检查是否可以下载文件 + * @param path 目标路径 + * @param downloadSize 下载文件大小(字节) + * @param requiredFreeSpace 额外需要的空闲空间(字节),默认为0 + * @return bool true-可以下载,false-空间不足 + */ + bool CanDownloadFile(const std::string &path, uint64_t downloadSize, uint64_t requiredFreeSpace = 0); + + /** + * @brief 检查系统内存是否充足 + * @param requiredSize 需要的空间大小(字节) + * @return bool true-内存充足,false-内存不足 + */ + bool IsMemorySufficient(uint64_t requiredSize); + + /** + * @brief 获取指定路径的可用内存 + * @param path 路径,默认为"/user/" + * @return uint64_t 可用内存大小(字节) + */ + uint64_t GetAvailableMemory(const std::string &path = "/user/"); + + /** + * @brief 获取文件夹大小 + * @param folderPath 文件夹路径 + * @return uint64_t 文件夹大小(字节) + */ + uint64_t GetFolderSize(const char *folderPath); + + /** + * @brief 获取系统内存信息字符串 + * @return std::string 格式化的内存信息字符串 + */ + std::string GetSystemMemoryInfo(); + + /** + * @brief 获取系统总内存 + * @return uint64_t 总内存大小(字节) + */ + uint64_t GetTotalMemory(); + + /** + * @brief 获取系统已用内存 + * @return uint64_t 已用内存大小(字节) + */ + uint64_t GetUsedMemory(); + + /** + * @brief 获取系统剩余内存 + * @return uint64_t 剩余内存大小(字节) + */ + uint64_t GetFreeMemory(); + + /** + * @brief 检查指定路径的内存是否充足 + * @param path 路径 + * @param requiredSize 需要的空间大小(字节) + * @return bool true-内存充足,false-内存不足 + */ + bool CheckPathMemory(const std::string &path, uint64_t requiredSize); + + /** + * @brief 获取内存清理建议 + * @return std::string 清理建议字符串 + */ + std::string GetMemoryCleanupSuggestions(); + + private: + /** + * @brief 构造函数(私有) + */ + MemoryManager(); + + /** + * @brief 析构函数(私有) + */ + virtual ~MemoryManager(); + + /** + * @brief 禁用拷贝构造函数 + */ + MemoryManager(const MemoryManager &) = delete; + + /** + * @brief 禁用赋值操作符 + */ + MemoryManager &operator=(const MemoryManager &) = delete; + + /** + * @brief 递归计算文件夹大小 + * @param folderPath 文件夹路径 + * @return uint64_t 文件夹大小(字节) + */ + uint64_t CalculateFolderSize(const char *folderPath); + + /** + * @brief 获取文件系统信息 + * @param path 路径 + * @param totalSize 输出总大小(字节) + * @param freeSize 输出剩余大小(字节) + * @param usedSize 输出已用大小(字节) + * @return bool true-成功,false-失败 + */ + bool GetFileSystemInfo(const std::string &path, uint64_t &totalSize, uint64_t &freeSize, uint64_t &usedSize); + + }; +} + +#endif // MEMORY_MANAGER_H diff --git a/code/sdk/application/wearable/ln/nativeapp/nativeui/system/src/MemoryManager.cpp b/code/sdk/application/wearable/ln/nativeapp/nativeui/system/src/MemoryManager.cpp new file mode 100644 index 000000000..7f0f53453 --- /dev/null +++ b/code/sdk/application/wearable/ln/nativeapp/nativeui/system/src/MemoryManager.cpp @@ -0,0 +1,296 @@ +/* + * @Author: Assistant + * @Date: 2024-12-19 + * @Description: Memory Manager - 内存管理模块实现 + */ +#include "system/include/MemoryManager.h" +#include "wearable_log.h" +#include "custom_utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace OHOS +{ + static MemoryManager *g_pMemoryManager = nullptr; + + /** + * @brief 构造函数 + * @details 初始化MemoryManager实例,设置全局指针 + */ + MemoryManager::MemoryManager() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MemoryManager::MemoryManager"); + g_pMemoryManager = this; + } + + /** + * @brief 析构函数 + * @details 清理资源,重置全局指针 + */ + MemoryManager::~MemoryManager() + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MemoryManager::~MemoryManager"); + g_pMemoryManager = nullptr; + } + + /** + * @brief 获取MemoryManager单例实例 + * @return MemoryManager* 单例实例指针 + */ + MemoryManager *MemoryManager::GetInstance() + { + if (g_pMemoryManager == nullptr) { + g_pMemoryManager = new MemoryManager(); + } + return g_pMemoryManager; + } + + /** + * @brief 检查是否可以下载文件 + * @param path 目标路径 + * @param downloadSize 下载文件大小(字节) + * @param requiredFreeSpace 额外需要的空闲空间(字节),默认为0 + * @return bool true-可以下载,false-空间不足 + */ + bool MemoryManager::CanDownloadFile(const std::string &path, uint64_t downloadSize, uint64_t requiredFreeSpace) + { + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "MemoryManager::CanDownloadFile: path=%s, downloadSize=%llu, requiredFreeSpace=%llu", + path.c_str(), downloadSize, requiredFreeSpace); + + // 获取目标路径的已用空间 + uint64_t usedSpace = GetFolderSize(path.c_str()); + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Current used space: %llu bytes", usedSpace); + + // 计算总需求空间 + uint64_t totalRequired = usedSpace + downloadSize + requiredFreeSpace; + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Total required space: %llu bytes", totalRequired); + + // 获取文件系统信息 + uint64_t totalSize, freeSize, usedSize; + if (!GetFileSystemInfo(path, totalSize, freeSize, usedSize)) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to get filesystem info for path: %s", path.c_str()); + return false; + } + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Filesystem info - Total: %llu, Free: %llu, Used: %llu", + totalSize, freeSize, usedSize); + + // 检查是否有足够空间 + bool hasEnoughSpace = (freeSize >= downloadSize + requiredFreeSpace); + + WEARABLE_LOGD(WEARABLE_LOG_MODULE_APP, "Memory check result: %s", hasEnoughSpace ? "SUFFICIENT" : "INSUFFICIENT"); + + return hasEnoughSpace; + } + + + + /** + * @brief 获取指定路径的可用内存 + * @param path 路径 + * @return uint64_t 可用内存大小(字节) + */ + uint64_t MemoryManager::GetAvailableMemory(const std::string &path) + { + uint64_t totalSize, freeSize, usedSize; + if (GetFileSystemInfo(path, totalSize, freeSize, usedSize)) { + return freeSize; + } + return 0; + } + + /** + * @brief 获取文件夹大小 + * @param folderPath 文件夹路径 + * @return uint64_t 文件夹大小(字节) + */ + uint64_t MemoryManager::GetFolderSize(const char *folderPath) + { + return CalculateFolderSize(folderPath); + } + + /** + * @brief 获取系统内存信息字符串 + * @return std::string 格式化的内存信息字符串 + */ + std::string MemoryManager::GetSystemMemoryInfo() + { + std::stringstream result; + + // 获取文件系统信息(只显示一次) + uint64_t totalSize, freeSize, usedSize; + if (GetFileSystemInfo("/user/", totalSize, freeSize, usedSize)) { + result << "[User Root]" << std::endl; + result << " Path: /user/" << std::endl; + result << " Total: " << totalSize / 1024 << " KB (" << totalSize / (1024 * 1024) << " MB)" << std::endl; + result << " Used: " << usedSize / 1024 << " KB (" << usedSize / (1024 * 1024) << " MB)" << std::endl; + result << " Free: " << freeSize / 1024 << " KB (" << freeSize / (1024 * 1024) << " MB)" << std::endl; + result << " Usage: " << (totalSize > 0 ? (double)usedSize * 100.0 / totalSize : 0.0) << "%" << std::endl; + result << " ====================" << std::endl; + } + + // 获取各个目录的文件夹大小 + std::vector> directories = { + {"/user/update/", "更新文件"}, + {"/user/res/", "资源文件"}, + {"/user/system/", "系统文件"}, + {"/user/userdata/", "用户数据"} + }; + + result << std::endl << "[Directory Usage]" << std::endl; + for (const auto &dir : directories) { + uint64_t folderSize = GetFolderSize(dir.first.c_str()); + if (folderSize > 0) { + result << " " << dir.second << ": " << folderSize / 1024 << " KB (" << folderSize / (1024 * 1024) << " MB)" << std::endl; + } + } + + return result.str().empty() ? "No memory information available." : result.str(); + } + + /** + * @brief 获取系统总内存 + * @return uint64_t 总内存大小(字节) + */ + uint64_t MemoryManager::GetTotalMemory() + { + uint64_t totalSize, freeSize, usedSize; + if (GetFileSystemInfo("/user/", totalSize, freeSize, usedSize)) { + return totalSize; + } + return 0; + } + + /** + * @brief 获取系统已用内存 + * @return uint64_t 已用内存大小(字节) + */ + uint64_t MemoryManager::GetUsedMemory() + { + uint64_t totalSize, freeSize, usedSize; + if (GetFileSystemInfo("/user/", totalSize, freeSize, usedSize)) { + return usedSize; + } + return 0; + } + + /** + * @brief 获取系统剩余内存 + * @return uint64_t 剩余内存大小(字节) + */ + uint64_t MemoryManager::GetFreeMemory() + { + return GetAvailableMemory("/user/"); + } + + /** + * @brief 检查指定路径的内存是否充足 + * @param path 路径 + * @param requiredSize 需要的空间大小(字节) + * @return bool true-内存充足,false-内存不足 + */ + bool MemoryManager::CheckPathMemory(const std::string &path, uint64_t requiredSize) + { + return CanDownloadFile(path, requiredSize, 0); + } + + /** + * @brief 获取内存清理建议 + * @return std::string 清理建议字符串 + */ + std::string MemoryManager::GetMemoryCleanupSuggestions() + { + std::stringstream suggestions; + + // 检查各个目录的使用情况 + std::vector> directories = { + {"/user/music/", "音乐文件"}, + {"/user/dial/", "表盘文件"}, + {"/user/userdata/", "用户数据"}, + {"/user/res/", "资源文件"} + }; + + suggestions << "内存清理建议:" << std::endl; + + for (const auto &dir : directories) { + uint64_t size = GetFolderSize(dir.first.c_str()); + if (size > 10 * 1024 * 1024) { // 大于10MB + suggestions << "- " << dir.second << "占用 " << size / 1024 / 1024 << "MB" << std::endl; + } + } + + return suggestions.str(); + } + + /** + * @brief 递归计算文件夹大小 + * @param folderPath 文件夹路径 + * @return uint64_t 文件夹大小(字节) + */ + uint64_t MemoryManager::CalculateFolderSize(const char *folderPath) + { + DIR *dir; + struct dirent *entry; + struct stat fileStat; + uint64_t totalSize = 0; + + dir = opendir(folderPath); + if (dir == NULL) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error opening directory: %s", folderPath); + return 0; + } + + while ((entry = readdir(dir)) != NULL) { + char filePath[1024]; + snprintf(filePath, sizeof(filePath), "%s/%s", folderPath, entry->d_name); + + if (stat(filePath, &fileStat) == -1) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Error getting file status: %s", filePath); + continue; + } + + if (S_ISDIR(fileStat.st_mode)) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { + continue; + } + totalSize += CalculateFolderSize(filePath); + } else { + totalSize += fileStat.st_size; + } + } + + closedir(dir); + return totalSize; + } + + /** + * @brief 获取文件系统信息 + * @param path 路径 + * @param totalSize 输出总大小(字节) + * @param freeSize 输出剩余大小(字节) + * @param usedSize 输出已用大小(字节) + * @return bool true-成功,false-失败 + */ + bool MemoryManager::GetFileSystemInfo(const std::string &path, uint64_t &totalSize, uint64_t &freeSize, uint64_t &usedSize) + { + struct statfs file_buf = {0}; + + if (statfs(path.c_str(), &file_buf) != 0) { + WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "Failed to get filesystem info for: %s", path.c_str()); + return false; + } + + totalSize = static_cast(file_buf.f_blocks) * file_buf.f_bsize; + freeSize = static_cast(file_buf.f_bfree) * file_buf.f_bsize; + usedSize = totalSize - freeSize; + + return true; + } +}