storage_manager支持设备剩余空间不足时清理应用缓存能力

Signed-off-by: william <william.ligang@huawei.com>
This commit is contained in:
william 2024-06-27 23:49:25 -07:00
parent 9d75ae1ec3
commit 1ca2fa76e6
13 changed files with 356 additions and 80 deletions

View File

@ -40,7 +40,8 @@
"common_event_service",
"data_share",
"dfs_service",
"exfatprogs",
"exfatprogs",
"eventhandler",
"FreeBSD",
"file_api",
"gptfdisk",

View File

@ -916,7 +916,7 @@ int32_t MountManager::RestoreconSystemServiceDirs(int32_t userId)
for (const DirInfo &dir : systemServiceDir_) {
std::string path = StringPrintf(dir.path.c_str(), userId);
RestoreconRecurse(path.c_str());
LOGD("systemServiceDir_ RestoreconRecurse path is %{private}s ", path.c_str());
LOGD("systemServiceDir_ RestoreconRecurse path is %{public}s ", path.c_str());
}
#endif
return err;

View File

@ -85,6 +85,8 @@ ohos_shared_library("storage_manager") {
defines += [ "STORAGE_STATISTICS_MANAGER" ]
sources += [
"account_subscriber/account_subscriber.cpp",
"storage/src/bundle_manager_connector.cpp",
"storage/src/storage_monitor_service.cpp",
"storage/src/storage_status_service.cpp",
"storage/src/storage_total_status_service.cpp",
"storage/src/volume_storage_status_service.cpp",
@ -95,6 +97,7 @@ ohos_shared_library("storage_manager") {
"bundle_framework:appexecfwk_base",
"bundle_framework:appexecfwk_core",
"data_share:datashare_consumer",
"eventhandler:libeventhandler",
"relational_store:native_rdb",
]

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_STORAGE_MANAGER_BUNDLE_MANAGER_CONNECTOR_H
#define OHOS_STORAGE_MANAGER_BUNDLE_MANAGER_CONNECTOR_H
#include <nocopyable.h>
#include <singleton.h>
#include <iostream>
#include "bundle_stats.h"
#include "bundle_mgr_interface.h"
#include "bundle_mgr_proxy.h"
#include "iremote_object.h"
namespace OHOS {
namespace StorageManager {
class BundleMgrConnector : public NoCopyable {
DECLARE_DELAYED_SINGLETON(BundleMgrConnector);
public:
sptr<AppExecFwk::IBundleMgr> GetBundleMgrProxy();
int32_t ResetBundleMgrProxy();
private:
std::mutex mutex_;
sptr<AppExecFwk::IBundleMgr> bundleMgr_ = nullptr;
sptr<IRemoteObject::DeathRecipient> deathRecipient_ = nullptr;
};
class BundleMgrDeathRecipient : public IRemoteObject::DeathRecipient {
public:
BundleMgrDeathRecipient() = default;
virtual ~BundleMgrDeathRecipient() = default;
virtual void OnRemoteDied(const wptr<IRemoteObject> &object);
};
} // StorageManager
} // OHOS
#endif // OHOS_STORAGE_MANAGER_BUNDLE_MANAGER_CONNECTOR_H

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef OHOS_STORAGE_MANAGER_STORAGE_MONITOR_SERVICE_H
#define OHOS_STORAGE_MANAGER_STORAGE_MONITOR_SERVICE_H
#include <iostream>
#include <nocopyable.h>
#include <singleton.h>
#include <thread>
#include <vector>
#include "event_handler.h"
namespace OHOS {
namespace StorageManager {
class StorageMonitorService : public NoCopyable {
DECLARE_DELAYED_SINGLETON(StorageMonitorService);
public:
void StartStorageMonitorTask();
private:
void StartEventHandler();
void Execute();
void CheckAndCleanBundleCache();
int64_t GetLowerThreshold(int64_t totalSize);
std::mutex eventMutex_;
std::thread eventThread_;
std::condition_variable eventCon_;
std::shared_ptr<AppExecFwk::EventHandler> eventHandler_ = nullptr;
};
} // StorageManager
} // OHOS
#endif // OHOS_STORAGE_MANAGER_STORAGE_MONITOR_SERVICE_H

View File

@ -22,7 +22,6 @@
#include <iostream>
#include "bundle_stats.h"
#include "storage_stats.h"
#include "bundle_mgr_interface.h"
#include "iremote_object.h"
namespace OHOS {
@ -39,29 +38,16 @@ public:
int32_t GetBundleStats(const std::string &pkgName, int32_t userId, BundleStats &bundleStats);
int32_t GetBundleStatsForIncrease(uint32_t userId, const std::vector<std::string> &bundleNames,
const std::vector<int64_t> &incrementalBackTimes, std::vector<int64_t> &pkgFileSizes);
int32_t ResetBundleMgrProxy();
private:
int GetCurrentUserId();
std::string GetCallingPkgName();
int32_t ConnectBundleMgr();
int32_t GetAppSize(int32_t userId, int64_t &size);
const std::vector<std::string> dataDir = {"app", "local", "distributed", "database", "cache"};
sptr<AppExecFwk::IBundleMgr> bundleMgr_ = nullptr;
sptr<IRemoteObject::DeathRecipient> deathRecipient_ = nullptr;
std::mutex mutex_;
const int DEFAULT_USER_ID = 100;
enum BUNDLE_STATS {APP = 0, LOCAL, DISTRIBUTED, DATABASE, CACHE};
enum BUNDLE_STATS_RESULT {APPSIZE = 0, CACHESIZE, DATASIZE};
};
class BundleMgrDeathRecipient : public IRemoteObject::DeathRecipient {
public:
BundleMgrDeathRecipient() = default;
virtual ~BundleMgrDeathRecipient() = default;
virtual void OnRemoteDied(const wptr<IRemoteObject> &object);
};
} // StorageManager
} // OHOS

View File

@ -17,6 +17,7 @@
#include <singleton.h>
#ifdef STORAGE_STATISTICS_MANAGER
#include <storage/storage_monitor_service.h>
#include <storage/storage_status_service.h>
#include <storage/storage_total_status_service.h>
#include <storage/volume_storage_status_service.h>
@ -46,6 +47,9 @@ void StorageManager::OnStart()
LOGI("StorageManager::OnStart Begin");
bool res = SystemAbility::Publish(this);
AddSystemAbilityListener(COMMON_EVENT_SERVICE_ID);
#ifdef STORAGE_STATISTICS_MANAGER
DelayedSingleton<StorageMonitorService>::GetInstance()->StartStorageMonitorTask();
#endif
LOGI("StorageManager::OnStart End, res = %{public}d", res);
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "storage/bundle_manager_connector.h"
#include <cstdlib>
#include <cstring>
#include <mntent.h>
#include <singleton.h>
#include <sys/statvfs.h>
#include <unordered_set>
#include "iservice_registry.h"
#include "storage_service_errno.h"
#include "storage_service_log.h"
#include "system_ability_definition.h"
namespace OHOS {
namespace StorageManager {
BundleMgrConnector::BundleMgrConnector() {}
BundleMgrConnector::~BundleMgrConnector()
{
bundleMgr_ = nullptr;
deathRecipient_ = nullptr;
}
sptr<AppExecFwk::IBundleMgr> BundleMgrConnector::GetBundleMgrProxy()
{
std::lock_guard<std::mutex> lock(mutex_);
if (bundleMgr_ == nullptr) {
auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (sam == nullptr) {
LOGE("BundleMgrConnector::GetBundleMgrProxy samgr == nullptr");
return nullptr;
}
sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
if (!remoteObject) {
LOGE("BundleMgrConnector::GetBundleMgrProxy remoteObj == nullptr");
return nullptr;
}
bundleMgr_ = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
if (bundleMgr_ == nullptr) {
LOGE("BundleMgrConnector::GetBundleMgrProxy bundleMgr == nullptr");
return nullptr;
}
deathRecipient_ = new (std::nothrow) BundleMgrDeathRecipient();
if (!deathRecipient_) {
LOGE("BundleMgrConnector::GetBundleMgrProxy failed to create death recipient");
bundleMgr_ = nullptr;
return nullptr;
}
bundleMgr_->AsObject()->AddDeathRecipient(deathRecipient_);
}
return bundleMgr_;
}
int32_t BundleMgrConnector::ResetBundleMgrProxy()
{
std::lock_guard<std::mutex> lock(mutex_);
if ((bundleMgr_ != nullptr) && (bundleMgr_->AsObject() != nullptr)) {
bundleMgr_->AsObject()->RemoveDeathRecipient(deathRecipient_);
}
bundleMgr_ = nullptr;
return E_OK;
}
void BundleMgrDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
{
DelayedSingleton<BundleMgrConnector>::GetInstance()->ResetBundleMgrProxy();
}
} // StorageManager
} // OHOS

View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "storage/storage_monitor_service.h"
#include <cstdlib>
#include <cstring>
#include <mntent.h>
#include <pthread.h>
#include <singleton.h>
#include <sys/statvfs.h>
#include <unordered_set>
#include "storage_service_errno.h"
#include "storage_service_log.h"
#include "storage/bundle_manager_connector.h"
#include "storage/storage_total_status_service.h"
namespace OHOS {
namespace StorageManager {
constexpr int32_t CONST_NUM_TWO = 2;
constexpr int32_t CONST_NUM_THREE = 3;
constexpr int32_t CONST_NUM_ONE_HUNDRED = 100;
constexpr int32_t WAIT_THREAD_TIMEOUT_MS = 5;
constexpr int32_t DEFAULT_CHECK_INTERVAL = 60 * 1000; // 60s
constexpr int32_t STORAGE_THRESHOLD_PERCENTAGE = 5; // 5%
constexpr int64_t STORAGE_THRESHOLD_MAX_BYTES = 500 * 1024 * 1024; // 500M
StorageMonitorService::StorageMonitorService() {}
StorageMonitorService::~StorageMonitorService()
{
LOGD("StorageMonitorService Destructor.");
std::unique_lock<std::mutex> lock(eventMutex_);
if ((eventHandler_ != nullptr) && (eventHandler_->GetEventRunner() != nullptr)) {
eventHandler_->RemoveAllEvents();
eventHandler_->GetEventRunner()->Stop();
}
if (eventThread_.joinable()) {
eventThread_.join();
}
eventHandler_ = nullptr;
}
void StorageMonitorService::StartStorageMonitorTask()
{
LOGI("StorageMonitorService, start deicve storage monitor task.");
std::unique_lock<std::mutex> lock(eventMutex_);
if (eventHandler_ == nullptr) {
eventThread_ = std::thread(&StorageMonitorService::StartEventHandler, this);
eventCon_.wait_for(lock, std::chrono::seconds(WAIT_THREAD_TIMEOUT_MS), [this] {
return eventHandler_ != nullptr;
});
}
auto executeFunc = [this] { Execute(); };
eventHandler_->PostTask(executeFunc, DEFAULT_CHECK_INTERVAL);
}
void StorageMonitorService::StartEventHandler()
{
pthread_setname_np(pthread_self(), "storage_monitor_task_event");
auto runner = AppExecFwk::EventRunner::Create(false);
if (runner == nullptr) {
LOGE("event runner is nullptr.");
return;
}
{
std::lock_guard<std::mutex> lock(eventMutex_);
eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(runner);
}
eventCon_.notify_one();
runner->Run();
}
void StorageMonitorService::Execute()
{
if (eventHandler_ == nullptr) {
LOGE("event handler is nullptr.");
return;
}
CheckAndCleanBundleCache();
auto executeFunc = [this] { Execute(); };
eventHandler_->PostTask(executeFunc, DEFAULT_CHECK_INTERVAL);
}
void StorageMonitorService::CheckAndCleanBundleCache()
{
int64_t totalSize;
int32_t err = DelayedSingleton<StorageTotalStatusService>::GetInstance()->GetTotalSize(totalSize);
if ((err != E_OK) || (totalSize <= 0)) {
LOGE("Get device total size failed.");
return;
}
int64_t freeSize;
err = DelayedSingleton<StorageTotalStatusService>::GetInstance()->GetFreeSize(freeSize);
if ((err != E_OK) || (freeSize <= 0)) {
LOGE("Get device free size failed.");
return;
}
int64_t lowThreshold = GetLowerThreshold(totalSize);
if (lowThreshold <= 0) {
LOGE("Lower threshold value is invalid.");
return;
}
LOGD("Device storage freeSize=%{public}lld, threshold=%{public}lld", static_cast<long long>(freeSize),
static_cast<long long>(lowThreshold));
if (freeSize >= (lowThreshold * CONST_NUM_THREE) / CONST_NUM_TWO) {
LOGD("The cache clean threshold had not been reached, skip this clean task.");
return;
}
auto bundleMgr = DelayedSingleton<BundleMgrConnector>::GetInstance()->GetBundleMgrProxy();
if (bundleMgr == nullptr) {
LOGE("Connect bundle manager sa proxy failed.");
return;
}
LOGD("Device storage free size not enough, start clean bundle cache files automatic.");
auto ret = bundleMgr->CleanBundleCacheFilesAutomatic(lowThreshold * CONST_NUM_TWO);
if (ret != ERR_OK) {
LOGE("Invoke bundleMgr interface to clean bundle cache files automatic failed.");
}
}
int64_t StorageMonitorService::GetLowerThreshold(int64_t totalSize)
{
int64_t lowBytes = (totalSize * STORAGE_THRESHOLD_PERCENTAGE) / CONST_NUM_ONE_HUNDRED;
return (lowBytes < STORAGE_THRESHOLD_MAX_BYTES) ? lowBytes : STORAGE_THRESHOLD_MAX_BYTES;
}
} // StorageManager
} // OHOS

View File

@ -22,9 +22,8 @@
#include "storage_service_constant.h"
#include "storage_service_errno.h"
#include "storage_service_log.h"
#include "storage/bundle_manager_connector.h"
#include "storage/storage_total_status_service.h"
#include "bundle_mgr_interface.h"
#include "bundle_mgr_proxy.h"
#include "application_info.h"
#include "iservice_registry.h"
#include "system_ability_definition.h"
@ -174,10 +173,10 @@ int32_t StorageStatusService::GetCurrentBundleStats(BundleStats &bundleStats)
int32_t StorageStatusService::GetBundleStats(const std::string &pkgName, int32_t userId, BundleStats &pkgStats)
{
HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
int32_t err = ConnectBundleMgr();
if (err != E_OK) {
auto bundleMgr = DelayedSingleton<BundleMgrConnector>::GetInstance()->GetBundleMgrProxy();
if (bundleMgr == nullptr) {
LOGE("StorageStatusService::GetBundleStats connect bundlemgr failed");
return err;
return E_SERVICE_IS_NULLPTR;
}
if (userId < 0 || userId > StorageService::MAX_USER_ID) {
@ -186,7 +185,7 @@ int32_t StorageStatusService::GetBundleStats(const std::string &pkgName, int32_t
}
vector<int64_t> bundleStats;
bool res = bundleMgr_->GetBundleStats(pkgName, userId, bundleStats);
bool res = bundleMgr->GetBundleStats(pkgName, userId, bundleStats);
if (!res || bundleStats.size() != dataDir.size()) {
LOGE("StorageStatusService::An error occurred in querying bundle stats.");
return E_BUNDLEMGR_ERROR;
@ -203,52 +202,17 @@ int32_t StorageStatusService::GetBundleStats(const std::string &pkgName, int32_t
return E_OK;
}
int32_t StorageStatusService::ConnectBundleMgr()
{
LOGD("connect begin");
std::lock_guard<std::mutex> lock(mutex_);
if (bundleMgr_ == nullptr) {
auto sam = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
if (sam == nullptr) {
LOGE("StorageStatusService::ConnectBundleMgr samgr == nullptr");
return E_SA_IS_NULLPTR;
}
sptr<IRemoteObject> remoteObject = sam->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
if (!remoteObject) {
LOGE("StorageStatusService::ConnectBundleMgr remoteObj == nullptr");
return E_REMOTE_IS_NULLPTR;
}
bundleMgr_ = iface_cast<AppExecFwk::IBundleMgr>(remoteObject);
if (bundleMgr_ == nullptr) {
LOGE("StorageStatusService::ConnectBundleMgr bundleMgr == nullptr");
return E_SERVICE_IS_NULLPTR;
}
deathRecipient_ = new (std::nothrow) BundleMgrDeathRecipient();
if (!deathRecipient_) {
LOGE("StorageStatusService::ConnectBundleMgr failed to create death recipient");
return E_DEATH_RECIPIENT_IS_NULLPTR;
}
bundleMgr_->AsObject()->AddDeathRecipient(deathRecipient_);
}
LOGD("connect end");
return E_OK;
}
int32_t StorageStatusService::GetAppSize(int32_t userId, int64_t &appSize)
{
HITRACE_METER_NAME(HITRACE_TAG_FILEMANAGEMENT, __PRETTY_FUNCTION__);
int32_t err = ConnectBundleMgr();
if (err != E_OK) {
auto bundleMgr = DelayedSingleton<BundleMgrConnector>::GetInstance()->GetBundleMgrProxy();
if (bundleMgr == nullptr) {
LOGE("StorageStatusService::GetUserStorageStats connect bundlemgr failed");
return err;
return E_SERVICE_IS_NULLPTR;
}
vector<int64_t> bundleStats;
bool res = bundleMgr_->GetAllBundleStats(userId, bundleStats);
bool res = bundleMgr->GetAllBundleStats(userId, bundleStats);
if (!res || bundleStats.size() != dataDir.size()) {
LOGE("StorageStatusService::GetAllBundleStats fail. res %{public}d, bundleStats.size %{public}zu",
res, bundleStats.size());
@ -263,23 +227,6 @@ int32_t StorageStatusService::GetAppSize(int32_t userId, int64_t &appSize)
return E_OK;
}
int32_t StorageStatusService::ResetBundleMgrProxy()
{
LOGD("enter");
std::lock_guard<std::mutex> lock(mutex_);
if ((bundleMgr_ != nullptr) && (bundleMgr_->AsObject() != nullptr)) {
bundleMgr_->AsObject()->RemoveDeathRecipient(deathRecipient_);
}
bundleMgr_ = nullptr;
return E_OK;
}
void BundleMgrDeathRecipient::OnRemoteDied(const wptr<IRemoteObject> &remote)
{
DelayedSingleton<StorageStatusService>::GetInstance()->ResetBundleMgrProxy();
}
int32_t StorageStatusService::GetUserStorageStatsByType(int32_t userId, StorageStats &storageStats, std::string type)
{
storageStats.video_ = 0;

View File

@ -26,6 +26,8 @@ ohos_unittest("storage_total_status_service_test") {
sources = [
"${storage_daemon_path}/ipc/src/storage_daemon_proxy.cpp",
"${storage_manager_path}/storage/src/bundle_manager_connector.cpp",
"${storage_manager_path}/storage/src/storage_monitor_service.cpp",
"${storage_manager_path}/storage/src/storage_status_service.cpp",
"${storage_manager_path}/storage/src/storage_total_status_service.cpp",
"${storage_manager_path}/storage_daemon_communication/src/storage_daemon_communication.cpp",

View File

@ -16,6 +16,7 @@
#include <cstdio>
#include <gtest/gtest.h>
#include "storage/bundle_manager_connector.h"
#include "storage/storage_status_service.h"
#include "storage/storage_total_status_service.h"
#include "storage_service_errno.h"
@ -200,7 +201,7 @@ HWTEST_F(StorageTotalStatusServiceTest, Storage_status_GetCurrentBundleStats_000
HWTEST_F(StorageTotalStatusServiceTest, Storage_total_status_ResetBundleMgrProxy_0000, testing::ext::TestSize.Level1)
{
GTEST_LOG_(INFO) << "StorageTotalStatusServiceTest-begin Storage_total_status_ResetBundleMgrProxy_0000";
std::shared_ptr<StorageStatusService> service = DelayedSingleton<StorageStatusService>::GetInstance();
std::shared_ptr<BundleMgrConnector> service = DelayedSingleton<BundleMgrConnector>::GetInstance();
int64_t result = service->ResetBundleMgrProxy();
EXPECT_GE(result, 0);
GTEST_LOG_(INFO) << "StorageTotalStatusServiceTest-end Storage_total_status_ResetBundleMgrProxy_0000";

View File

@ -13,6 +13,7 @@
* limitations under the License.
*/
#include "storagestatusservice_fuzzer.h"
#include "storage/bundle_manager_connector.h"
#include "storage/storage_status_service.h"
#include "storage_service_log.h"
#include "storage_service_errno.h"
@ -48,7 +49,7 @@ bool StorageStatusServiceFuzzTest(const uint8_t *data, size_t size)
service->GetCurrentBundleStats(bundleStats);
service->GetBundleStats(pkgName, userId, bundleStats);
service->GetBundleStatsForIncrease(userId, bundleName, incrementalBackTimes, pkgFileSizes);
service->ResetBundleMgrProxy();
DelayedSingleton<BundleMgrConnector>::GetInstance()->ResetBundleMgrProxy();
return true;
}
} // namespace StorageManager