* Copyright (C) 2025 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 "hdc_subscriber.h"
#include <filesystem>
#include "credential_base.h"
using namespace Hdc;
using namespace OHOS::AccountSA;
namespace fs = std::filesystem;
namespace {
static const std::string USER_DIR_PREFIX_PATH = "/data/service/el1/public/hdc_server/";
static const mode_t MODE = (S_IRWXU | S_IRWXG | S_IXOTH | S_ISGID);
}
void HdcSubscriber::OnStateChanged(const OHOS::AccountSA::OsAccountStateData& data)
{
WRITE_LOG(LOG_INFO, "Recv data.state:%d, data.toId:%d", data.state, data.toId);
std::string path = USER_DIR_PREFIX_PATH + std::to_string(data.toId);
switch (data.state) {
case OsAccountState::CREATED:
if (!HdcCredentialBase::CreatePathWithMode(path.c_str(), MODE)) {
WRITE_LOG(LOG_FATAL, "Failed to create directory, error is:%s", strerror(errno));
}
break;
case OsAccountState::REMOVED:
if (HdcCredentialBase::RemovePath(path) != 0) {
WRITE_LOG(LOG_FATAL, "Failed to remove directory, error is:%s", strerror(errno));
}
break;
default:
WRITE_LOG(LOG_FATAL, "This state is not support,state is:%d", data.state);
break;
}
}
void HdcSubscriber::OnAccountsChanged(const int& )
{
}
int HdcAccountSubscriberMonitor()
{
static std::shared_ptr<HdcSubscriber> subscriber;
std::set<OsAccountState> states = { OsAccountState::CREATED, OsAccountState::REMOVED };
OsAccountSubscribeInfo subscribeInfo(states, false);
subscriber = std::make_shared<HdcSubscriber>(subscribeInfo);
const int maxRetry = 10;
int retryCount = 0;
while (retryCount < maxRetry &&
(OsAccountManager::SubscribeOsAccount(subscriber) != 0)) {
++retryCount;
std::this_thread::sleep_for(std::chrono::seconds(1));
WRITE_LOG(LOG_FATAL, "SubscribeOsAccount failed, %d/%d", retryCount, maxRetry);
}
if (retryCount < maxRetry) {
WRITE_LOG(LOG_DEBUG, "SubscribeOsAccount success.");
} else {
WRITE_LOG(LOG_FATAL, "SubscribeOsAccount failed after %d retries.", maxRetry);
return -1;
}
return 0;
}
void FreshAccountsPath()
{
std::vector<OHOS::AccountSA::OsAccountInfo> osAccountInfos;
OHOS::ErrCode err = OHOS::AccountSA::OsAccountManager::QueryAllCreatedOsAccounts(osAccountInfos);
if (err != 0) {
WRITE_LOG(LOG_FATAL, "QueryAllCreatedOsAccounts failed, error is:%d", err);
return;
}
std::error_code ec;
if (!fs::exists(USER_DIR_PREFIX_PATH, ec) || !fs::is_directory(USER_DIR_PREFIX_PATH, ec)) {
WRITE_LOG(LOG_FATAL, "User directory does not exist or is not a directory");
return;
}
std::vector<std::string> existUserIds;
for (const auto& info : osAccountInfos) {
existUserIds.push_back(std::to_string(info.GetLocalId()));
}
std::vector<std::string> existUserDirs;
for (const auto& entry : fs::directory_iterator(USER_DIR_PREFIX_PATH)) {
std::string dir = entry.path().filename().string();
if (HdcCredentialBase::IsUserDir(dir)) {
existUserDirs.push_back(dir);
}
}
std::vector<std::string> needCreate = HdcCredentialBase::Substract<std::string>(existUserIds, existUserDirs);
std::vector<std::string> needRemove = HdcCredentialBase::Substract<std::string>(existUserDirs, existUserIds);
for (const auto& item : needCreate) {
std::string path = USER_DIR_PREFIX_PATH + item;
if (!HdcCredentialBase::CreatePathWithMode(path.c_str(), MODE)) {
WRITE_LOG(LOG_FATAL, "Failed to create directory, error is:%s", strerror(errno));
}
}
for (const auto& item : needRemove) {
std::string path = USER_DIR_PREFIX_PATH + item;
if (HdcCredentialBase::RemovePath(path.c_str()) != 0) {
WRITE_LOG(LOG_FATAL, "Failed to remove directory, error is:%s", strerror(errno));
}
}
}