--- /dev/null
+/*
+ * @Author: Assistant
+ * @Date: 2024-12-19
+ * @Description: Memory Manager - 内存管理模块,用于OTA和表情文件下载时的内存检查
+ */
+#ifndef MEMORY_MANAGER_H
+#define MEMORY_MANAGER_H
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+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
--- /dev/null
+/*
+ * @Author: Assistant
+ * @Date: 2024-12-19
+ * @Description: Memory Manager - 内存管理模块实现
+ */
+#include "system/include/MemoryManager.h"
+#include "wearable_log.h"
+#include "custom_utils.h"
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <cstring>
+#include <sstream>
+#include <algorithm>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+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<std::pair<std::string, std::string>> 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<std::pair<std::string, std::string>> 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<uint64_t>(file_buf.f_blocks) * file_buf.f_bsize;
+ freeSize = static_cast<uint64_t>(file_buf.f_bfree) * file_buf.f_bsize;
+ usedSize = totalSize - freeSize;
+
+ return true;
+ }
+}