Files
chen 7e5d145276 add samgr hisysevent and hitrace
Signed-off-by: chen <chenkang40@huawei.com>
Change-Id: I5b48219f40b5491f10ecee8999c4b20b093a68d5
2022-06-25 14:47:07 +08:00

952 lines
34 KiB
C++

/*
* Copyright (c) 2021-2022 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 "system_ability_manager.h"
#include <cinttypes>
#include <unistd.h>
#include "ability_death_recipient.h"
#include "datetime_ex.h"
#include "directory_ex.h"
#include "errors.h"
#include "hisysevent_adapter.h"
#include "hitrace_meter.h"
#include "if_local_ability_manager.h"
#include "ipc_skeleton.h"
#include "local_ability_manager_proxy.h"
#include "parse_util.h"
#include "sam_log.h"
#include "service_control.h"
#include "string_ex.h"
#include "system_ability_definition.h"
#include "tools.h"
using namespace std;
namespace OHOS {
namespace {
const string PREFIX = "/system/profile/";
constexpr int32_t MAX_NAME_SIZE = 200;
constexpr int32_t SPLIT_NAME_VECTOR_SIZE = 2;
constexpr int32_t UID_ROOT = 0;
constexpr int32_t UID_SYSTEM = 1000;
constexpr int32_t MAX_SUBSCRIBE_COUNT = 256;
constexpr int64_t CHECK_LOADED_DELAY_TIME = 60 * 1000; // ms
}
std::mutex SystemAbilityManager::instanceLock;
sptr<SystemAbilityManager> SystemAbilityManager::instance;
SystemAbilityManager::SystemAbilityManager()
{
dBinderService_ = DBinderService::GetInstance();
}
SystemAbilityManager::~SystemAbilityManager()
{
}
void SystemAbilityManager::Init()
{
abilityDeath_ = sptr<IRemoteObject::DeathRecipient>(new AbilityDeathRecipient());
systemProcessDeath_ = sptr<IRemoteObject::DeathRecipient>(new SystemProcessDeathRecipient());
abilityStatusDeath_ = sptr<IRemoteObject::DeathRecipient>(new AbilityStatusDeathRecipient());
abilityCallbackDeath_ = sptr<IRemoteObject::DeathRecipient>(new AbilityCallbackDeathRecipient());
rpcCallbackImp_ = make_shared<RpcCallbackImp>();
if (workHandler_ == nullptr) {
auto runner = AppExecFwk::EventRunner::Create("workHandler");
workHandler_ = make_shared<AppExecFwk::EventHandler>(runner);
}
InitSaProfile();
}
const sptr<DBinderService> SystemAbilityManager::GetDBinder() const
{
return dBinderService_;
}
sptr<SystemAbilityManager> SystemAbilityManager::GetInstance()
{
std::lock_guard<std::mutex> autoLock(instanceLock);
if (instance == nullptr) {
instance = new SystemAbilityManager;
}
return instance;
}
void SystemAbilityManager::InitSaProfile()
{
if (workHandler_ == nullptr) {
HILOGE("InitSaProfile parseHandler_ not init!");
return;
}
auto callback = [this] () {
int64_t begin = GetTickCount();
std::vector<std::string> fileNames;
GetDirFiles(PREFIX, fileNames);
auto parser = std::make_shared<ParseUtil>();
for (const auto& file : fileNames) {
if (file.empty() || file.find(".xml") == std::string::npos
|| file.find("_trust.xml") != std::string::npos) {
continue;
}
parser->ParseSaProfiles(file);
}
auto saInfos = parser->GetAllSaProfiles();
lock_guard<mutex> autoLock(saProfileMapLock_);
for (const auto& saInfo : saInfos) {
saProfileMap_[saInfo.saId] = saInfo;
}
HILOGI("[PerformanceTest] InitSaProfile spend %{public}" PRId64 " ms", GetTickCount() - begin);
};
bool ret = workHandler_->PostTask(callback);
if (!ret) {
HILOGW("SystemAbilityManager::InitSaProfile PostTask fail");
}
}
bool SystemAbilityManager::GetSaProfile(int32_t saId, SaProfile& saProfile)
{
lock_guard<mutex> autoLock(saProfileMapLock_);
auto iter = saProfileMap_.find(saId);
if (iter == saProfileMap_.end()) {
return false;
} else {
saProfile = iter->second;
}
return true;
}
sptr<IRemoteObject> SystemAbilityManager::GetSystemAbility(int32_t systemAbilityId)
{
return CheckSystemAbility(systemAbilityId);
}
sptr<IRemoteObject> SystemAbilityManager::GetSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
{
return CheckSystemAbility(systemAbilityId, deviceId);
}
sptr<IRemoteObject> SystemAbilityManager::GetSystemAbilityFromRemote(int32_t systemAbilityId)
{
HILOGD("%{public}s called, systemAbilityId = %{public}d", __func__, systemAbilityId);
if (!CheckInputSysAbilityId(systemAbilityId)) {
HILOGW("GetSystemAbilityFromRemote invalid!");
return nullptr;
}
shared_lock<shared_mutex> readLock(abilityMapLock_);
auto iter = abilityMap_.find(systemAbilityId);
if (iter == abilityMap_.end()) {
HILOGI("GetSystemAbilityFromRemote not found service : %{public}d.", systemAbilityId);
return nullptr;
}
if (!(iter->second.isDistributed)) {
HILOGW("GetSystemAbilityFromRemote service : %{public}d not distributed", systemAbilityId);
return nullptr;
}
HILOGI("GetSystemAbilityFromRemote found service : %{public}d.", systemAbilityId);
return iter->second.remoteObj;
}
sptr<IRemoteObject> SystemAbilityManager::CheckSystemAbility(int32_t systemAbilityId)
{
HILOGD("%{public}s called, systemAbilityId = %{public}d", __func__, systemAbilityId);
ReportGetSAFrequency(IPCSkeleton::GetCallingPid(), systemAbilityId);
if (!CheckInputSysAbilityId(systemAbilityId)) {
HILOGW("CheckSystemAbility CheckSystemAbility invalid!");
return nullptr;
}
shared_lock<shared_mutex> readLock(abilityMapLock_);
auto iter = abilityMap_.find(systemAbilityId);
if (iter != abilityMap_.end()) {
HILOGI("found service : %{public}d.", systemAbilityId);
return iter->second.remoteObj;
}
HILOGW("NOT found service : %{public}d", systemAbilityId);
return nullptr;
}
bool SystemAbilityManager::CheckDistributedPermission()
{
auto callingUid = IPCSkeleton::GetCallingUid();
if (callingUid != UID_ROOT && callingUid != UID_SYSTEM) {
return false;
}
return true;
}
sptr<IRemoteObject> SystemAbilityManager::CheckSystemAbility(int32_t systemAbilityId,
const std::string& deviceId)
{
sptr<DBinderServiceStub> remoteBinder = nullptr;
if (dBinderService_ != nullptr) {
string strName = to_string(systemAbilityId);
HILOGI("CheckSystemAbility, MakeRemoteBinder begin, systemAbilityId is %{public}d, deviceId is %s",
systemAbilityId, deviceId.c_str());
remoteBinder = dBinderService_->MakeRemoteBinder(Str8ToStr16(strName), deviceId, systemAbilityId, 0);
if (remoteBinder == nullptr) {
HILOGE("MakeRemoteBinder error, remoteBinder is null, systemAbilityId is %{public}d, deviceId is %s",
systemAbilityId, deviceId.c_str());
} else {
HILOGI("CheckSystemAbility, MakeRemoteBinder end, systemAbilityId is %{public}d, deviceId is %s",
systemAbilityId, deviceId.c_str());
}
}
return remoteBinder;
}
int32_t SystemAbilityManager::FindSystemAbilityNotify(int32_t systemAbilityId, int32_t code)
{
return FindSystemAbilityNotify(systemAbilityId, "", code);
}
void SystemAbilityManager::NotifySystemAbilityChanged(int32_t systemAbilityId, const std::string& deviceId,
int32_t code, const sptr<ISystemAbilityStatusChange>& listener)
{
HILOGD("NotifySystemAbilityChanged, systemAbilityId = %{public}d", systemAbilityId);
if (listener == nullptr) {
HILOGE("%s listener null pointer!", __func__);
return;
}
switch (code) {
case ADD_SYSTEM_ABILITY_TRANSACTION: {
listener->OnAddSystemAbility(systemAbilityId, deviceId);
break;
}
case REMOVE_SYSTEM_ABILITY_TRANSACTION: {
listener->OnRemoveSystemAbility(systemAbilityId, deviceId);
break;
}
default:
break;
}
}
int32_t SystemAbilityManager::FindSystemAbilityNotify(int32_t systemAbilityId, const std::string& deviceId,
int32_t code)
{
HILOGI("%{public}s called:systemAbilityId = %{public}d, code = %{public}d", __func__, systemAbilityId, code);
lock_guard<recursive_mutex> autoLock(listenerMapLock_);
auto iter = listenerMap_.find(systemAbilityId);
if (iter != listenerMap_.end()) {
auto& listeners = iter->second;
for (const auto& item : listeners) {
NotifySystemAbilityChanged(systemAbilityId, deviceId, code, item.first);
}
}
return ERR_OK;
}
bool SystemAbilityManager::IsNameInValid(const std::u16string& name)
{
HILOGI("%{public}s called:name = %{public}s", __func__, Str16ToStr8(name).c_str());
bool ret = false;
if (name.empty() || name.size() > MAX_NAME_SIZE || DeleteBlank(name).empty()) {
ret = true;
}
return ret;
}
void SystemAbilityManager::StartOnDemandAbility(const std::u16string& procName, int32_t systemAbilityId)
{
lock_guard<recursive_mutex> autoLock(onDemandLock_);
auto iter = startingAbilityMap_.find(systemAbilityId);
if (iter == startingAbilityMap_.end()) {
return;
}
auto& abilityItem = iter->second;
StartOnDemandAbilityInner(procName, systemAbilityId, abilityItem);
}
void SystemAbilityManager::StartOnDemandAbilityInner(const std::u16string& procName, int32_t systemAbilityId,
AbilityItem& abilityItem)
{
if (abilityItem.state != AbilityState::INIT) {
return;
}
sptr<ILocalAbilityManager> procObject =
iface_cast<ILocalAbilityManager>(GetSystemProcess(procName));
if (procObject == nullptr) {
HILOGI("get process:%{public}s fail", Str16ToStr8(procName).c_str());
return;
}
procObject->StartAbility(systemAbilityId);
abilityItem.state = AbilityState::STARTING;
}
int32_t SystemAbilityManager::AddOnDemandSystemAbilityInfo(int32_t systemAbilityId,
const std::u16string& procName)
{
HILOGD("%{public}s called", __func__);
if (!CheckInputSysAbilityId(systemAbilityId) || IsNameInValid(procName)) {
HILOGW("AddOnDemandSystemAbilityInfo systemAbilityId or procName invalid.");
return ERR_INVALID_VALUE;
}
lock_guard<recursive_mutex> autoLock(onDemandLock_);
auto onDemandSaSize = onDemandAbilityMap_.size();
if (onDemandSaSize >= MAX_SERVICES) {
HILOGE("map size error, (Has been greater than %{public}zu)",
onDemandAbilityMap_.size());
return ERR_INVALID_VALUE;
}
if (systemProcessMap_.count(procName) == 0) {
HILOGW("AddOnDemandSystemAbilityInfo procName:%{public}s not exist.", Str16ToStr8(procName).c_str());
return ERR_INVALID_VALUE;
}
onDemandAbilityMap_[systemAbilityId] = procName;
HILOGI("insert onDemand systemAbilityId:%{public}d. size : %{public}zu", systemAbilityId,
onDemandAbilityMap_.size());
if (startingAbilityMap_.count(systemAbilityId) != 0) {
if (workHandler_ != nullptr) {
auto pendingTask = [procName, systemAbilityId, this] () {
StartOnDemandAbility(procName, systemAbilityId);
};
bool ret = workHandler_->PostTask(pendingTask);
if (!ret) {
HILOGW("AddOnDemandSystemAbilityInfo PostTask failed!");
}
}
}
return ERR_OK;
}
int32_t SystemAbilityManager::StartOnDemandAbility(int32_t systemAbilityId)
{
lock_guard<recursive_mutex> onDemandAbilityLock(onDemandLock_);
auto iter = onDemandAbilityMap_.find(systemAbilityId);
if (iter == onDemandAbilityMap_.end()) {
return ERR_INVALID_VALUE;
}
HILOGI("found onDemandAbility: %{public}d.", systemAbilityId);
AbilityItem& abilityItem = startingAbilityMap_[systemAbilityId];
StartOnDemandAbilityInner(iter->second, systemAbilityId, abilityItem);
return ERR_OK;
}
sptr<IRemoteObject> SystemAbilityManager::CheckSystemAbility(int32_t systemAbilityId, bool& isExist)
{
if (!CheckInputSysAbilityId(systemAbilityId)) {
return nullptr;
}
sptr<IRemoteObject> abilityProxy = CheckSystemAbility(systemAbilityId);
if (abilityProxy == nullptr) {
lock_guard<recursive_mutex> autoLock(onDemandLock_);
auto iter = startingAbilityMap_.find(systemAbilityId);
if (iter != startingAbilityMap_.end() && iter->second.state == AbilityState::STARTING) {
isExist = true;
return nullptr;
}
int32_t ret = StartOnDemandAbility(systemAbilityId);
if (ret == ERR_OK) {
isExist = true;
return nullptr;
}
isExist = false;
return nullptr;
}
isExist = true;
return abilityProxy;
}
int32_t SystemAbilityManager::RemoveSystemAbility(int32_t systemAbilityId)
{
if (!CheckInputSysAbilityId(systemAbilityId)) {
HILOGW("RemoveSystemAbility systemAbilityId:%{public}d", systemAbilityId);
return ERR_INVALID_VALUE;
}
{
unique_lock<shared_mutex> writeLock(abilityMapLock_);
auto itSystemAbility = abilityMap_.find(systemAbilityId);
if (itSystemAbility == abilityMap_.end()) {
HILOGI("SystemAbilityManager::RemoveSystemAbility not found!");
return ERR_INVALID_VALUE;
}
sptr<IRemoteObject> ability = itSystemAbility->second.remoteObj;
if (ability != nullptr && abilityDeath_ != nullptr) {
ability->RemoveDeathRecipient(abilityDeath_);
}
(void)abilityMap_.erase(itSystemAbility);
HILOGI("%s called, systemAbilityId : %{public}d, size : %{public}zu", __func__, systemAbilityId,
abilityMap_.size());
}
SendSystemAbilityRemovedMsg(systemAbilityId);
return ERR_OK;
}
int32_t SystemAbilityManager::RemoveSystemAbility(const sptr<IRemoteObject>& ability)
{
HILOGI("%s called, (ability)", __func__);
if (ability == nullptr) {
HILOGW("ability is nullptr ");
return ERR_INVALID_VALUE;
}
int32_t saId = 0;
{
unique_lock<shared_mutex> writeLock(abilityMapLock_);
for (auto iter = abilityMap_.begin(); iter != abilityMap_.end(); ++iter) {
if (iter->second.remoteObj == ability) {
saId = iter->first;
(void)abilityMap_.erase(iter);
if (abilityDeath_ != nullptr) {
ability->RemoveDeathRecipient(abilityDeath_);
}
HILOGI("%s called, systemAbilityId:%{public}d removed, size : %{public}zu", __func__, saId,
abilityMap_.size());
break;
}
}
}
if (saId != 0) {
SendSystemAbilityRemovedMsg(saId);
}
return ERR_OK;
}
vector<u16string> SystemAbilityManager::ListSystemAbilities(uint32_t dumpFlags)
{
vector<u16string> list;
shared_lock<shared_mutex> readLock(abilityMapLock_);
for (auto iter = abilityMap_.begin(); iter != abilityMap_.end(); iter++) {
list.emplace_back(Str8ToStr16(to_string(iter->first)));
}
return list;
}
int32_t SystemAbilityManager::SubscribeSystemAbility(int32_t systemAbilityId,
const sptr<ISystemAbilityStatusChange>& listener)
{
if (!CheckInputSysAbilityId(systemAbilityId) || listener == nullptr) {
HILOGW("SubscribeSystemAbility systemAbilityId or listener invalid!");
return ERR_INVALID_VALUE;
}
auto callingPid = IPCSkeleton::GetCallingPid();
{
lock_guard<recursive_mutex> autoLock(listenerMapLock_);
auto& listeners = listenerMap_[systemAbilityId];
for (const auto& itemListener : listeners) {
if (listener->AsObject() == itemListener.first->AsObject()) {
HILOGI("already exist listener object systemAbilityId = %{public}d", systemAbilityId);
return ERR_OK;
}
}
auto& count = subscribeCountMap_[callingPid];
if (count >= MAX_SUBSCRIBE_COUNT) {
HILOGE("SubscribeSystemAbility pid:%{public}d overflow max subscribe count!", callingPid);
return ERR_PERMISSION_DENIED;
}
++count;
if (abilityStatusDeath_ != nullptr) {
bool ret = listener->AsObject()->AddDeathRecipient(abilityStatusDeath_);
listeners.emplace_back(listener, callingPid);
HILOGI("SubscribeSystemAbility systemAbilityId = %{public}d AddDeathRecipient %{public}s",
systemAbilityId, ret ? "succeed" : "failed");
}
HILOGI("SubscribeSystemAbility systemAbilityId = %{public}d, size = %{public}zu", systemAbilityId,
listeners.size());
}
sptr<IRemoteObject> targetObject = CheckSystemAbility(systemAbilityId);
if (targetObject != nullptr) {
NotifySystemAbilityChanged(systemAbilityId, "", ADD_SYSTEM_ABILITY_TRANSACTION, listener);
}
return ERR_OK;
}
void SystemAbilityManager::UnSubscribeSystemAbilityLocked(
std::list<std::pair<sptr<ISystemAbilityStatusChange>, int32_t>>& listenerList,
const sptr<IRemoteObject>& listener)
{
auto iter = listenerList.begin();
while (iter != listenerList.end()) {
auto& item = *iter;
if (item.first->AsObject() != listener) {
++iter;
continue;
}
if (abilityStatusDeath_ != nullptr) {
listener->RemoveDeathRecipient(abilityStatusDeath_);
}
auto iterPair = subscribeCountMap_.find(item.second);
if (iterPair != subscribeCountMap_.end()) {
--iterPair->second;
if (iterPair->second == 0) {
subscribeCountMap_.erase(iterPair);
}
}
iter = listenerList.erase(iter);
break;
}
}
int32_t SystemAbilityManager::UnSubscribeSystemAbility(int32_t systemAbilityId,
const sptr<ISystemAbilityStatusChange>& listener)
{
if (!CheckInputSysAbilityId(systemAbilityId) || listener == nullptr) {
HILOGW("UnSubscribeSystemAbility systemAbilityId or listener invalid!");
return ERR_INVALID_VALUE;
}
lock_guard<recursive_mutex> autoLock(listenerMapLock_);
auto& listeners = listenerMap_[systemAbilityId];
UnSubscribeSystemAbilityLocked(listeners, listener->AsObject());
HILOGI("UnSubscribeSystemAbility systemAbilityId = %{public}d, size = %{public}zu", systemAbilityId,
listeners.size());
return ERR_OK;
}
void SystemAbilityManager::UnSubscribeSystemAbility(const sptr<IRemoteObject>& remoteObject)
{
lock_guard<recursive_mutex> autoLock(listenerMapLock_);
for (auto& item : listenerMap_) {
auto& listeners = item.second;
UnSubscribeSystemAbilityLocked(listeners, remoteObject);
}
HILOGI("UnSubscribeSystemAbility remote object dead!");
}
void SystemAbilityManager::SetDeviceName(const u16string &name)
{
deviceName_ = name;
}
const u16string& SystemAbilityManager::GetDeviceName() const
{
return deviceName_;
}
void SystemAbilityManager::NotifyRemoteSaDied(const std::u16string& name)
{
std::u16string saName;
std::string deviceId;
ParseRemoteSaName(name, deviceId, saName);
if (dBinderService_ != nullptr) {
std::string nodeId = TransformDeviceId(deviceId, NODE_ID, false);
dBinderService_->NoticeServiceDie(saName, nodeId);
HILOGI("NotifyRemoteSaDied, serviceName is %s, deviceId is %s",
Str16ToStr8(saName).c_str(), nodeId.c_str());
}
}
void SystemAbilityManager::NotifyRemoteDeviceOffline(const std::string& deviceId)
{
if (dBinderService_ != nullptr) {
dBinderService_->NoticeDeviceDie(deviceId);
HILOGI("NotifyRemoteDeviceOffline, deviceId is %s", deviceId.c_str());
}
}
void SystemAbilityManager::ParseRemoteSaName(const std::u16string& name, std::string& deviceId, std::u16string& saName)
{
vector<string> strVector;
SplitStr(Str16ToStr8(name), "_", strVector);
if (strVector.size() == SPLIT_NAME_VECTOR_SIZE) {
deviceId = strVector[0];
saName = Str8ToStr16(strVector[1]);
}
}
int32_t SystemAbilityManager::AddSystemAbility(int32_t systemAbilityId, const sptr<IRemoteObject>& ability,
const SAExtraProp& extraProp)
{
if (!CheckInputSysAbilityId(systemAbilityId) || ability == nullptr) {
HILOGE("AddSystemAbilityExtra input params is invalid.");
return ERR_INVALID_VALUE;
}
{
unique_lock<shared_mutex> writeLock(abilityMapLock_);
auto saSize = abilityMap_.size();
if (saSize >= MAX_SERVICES) {
HILOGE("map size error, (Has been greater than %zu)", saSize);
return ERR_INVALID_VALUE;
}
SAInfo saInfo;
saInfo.remoteObj = ability;
saInfo.isDistributed = extraProp.isDistributed;
saInfo.capability = extraProp.capability;
saInfo.permission = Str16ToStr8(extraProp.permission);
abilityMap_[systemAbilityId] = std::move(saInfo);
HILOGI("insert %{public}d. size : %{public}zu", systemAbilityId, abilityMap_.size());
}
RemoveCheckLoadedMsg(systemAbilityId);
if (abilityDeath_ != nullptr) {
ability->AddDeathRecipient(abilityDeath_);
}
u16string strName = Str8ToStr16(to_string(systemAbilityId));
if (extraProp.isDistributed && dBinderService_ != nullptr) {
dBinderService_->RegisterRemoteProxy(strName, systemAbilityId);
HILOGI("AddSystemAbility RegisterRemoteProxy, serviceId is %{public}d", systemAbilityId);
}
if (systemAbilityId == SOFTBUS_SERVER_SA_ID) {
if (dBinderService_ != nullptr && rpcCallbackImp_ != nullptr) {
bool ret = dBinderService_->StartDBinderService(rpcCallbackImp_);
HILOGI("start result is %{public}s", ret ? "succeed" : "fail");
}
}
SendSystemAbilityAddedMsg(systemAbilityId, ability);
return ERR_OK;
}
int32_t SystemAbilityManager::AddSystemProcess(const u16string& procName,
const sptr<IRemoteObject>& procObject)
{
if (procName.empty() || procObject == nullptr) {
HILOGE("AddSystemProcess empty name or null object!");
return ERR_INVALID_VALUE;
}
lock_guard<recursive_mutex> autoLock(onDemandLock_);
size_t procNum = systemProcessMap_.size();
if (procNum >= MAX_SERVICES) {
HILOGE("AddSystemProcess map size reach MAX_SERVICES already");
return ERR_INVALID_VALUE;
}
systemProcessMap_[procName] = procObject;
if (systemProcessDeath_ != nullptr) {
bool ret = procObject->AddDeathRecipient(systemProcessDeath_);
HILOGW("AddSystemProcess AddDeathRecipient %{public}s!", ret ? "succeed" : "failed");
}
HILOGI("AddSystemProcess insert %{public}s. size : %{public}zu", Str16ToStr8(procName).c_str(),
systemProcessMap_.size());
auto iterStarting = startingProcessMap_.find(procName);
if (iterStarting != startingProcessMap_.end()) {
int64_t end = GetTickCount();
HILOGI("[PerformanceTest] AddSystemProcess start process:%{public}s spend %{public}" PRId64 " ms",
Str16ToStr8(procName).c_str(), (end - iterStarting->second));
startingProcessMap_.erase(iterStarting);
}
return ERR_OK;
}
int32_t SystemAbilityManager::RemoveSystemProcess(const sptr<IRemoteObject>& procObject)
{
if (procObject == nullptr) {
HILOGW("RemoveSystemProcess null object!");
return ERR_INVALID_VALUE;
}
lock_guard<recursive_mutex> autoLock(onDemandLock_);
for (const auto& [procName, object] : systemProcessMap_) {
if (object == procObject) {
if (systemProcessDeath_ != nullptr) {
procObject->RemoveDeathRecipient(systemProcessDeath_);
}
std::string name = Str16ToStr8(procName);
(void)systemProcessMap_.erase(procName);
HILOGI("RemoveSystemProcess process:%{public}s dead, size : %{public}zu", name.c_str(),
systemProcessMap_.size());
return ERR_OK;
}
}
HILOGW("RemoveSystemProcess called and not found process.");
return ERR_INVALID_VALUE;
}
sptr<IRemoteObject> SystemAbilityManager::GetSystemProcess(const u16string& procName)
{
if (procName.empty()) {
HILOGE("GetSystemProcess empty name!");
return nullptr;
}
lock_guard<recursive_mutex> autoLock(onDemandLock_);
auto iter = systemProcessMap_.find(procName);
if (iter != systemProcessMap_.end()) {
HILOGI("process:%{public}s found", Str16ToStr8(procName).c_str());
return iter->second;
}
HILOGE("process:%{public}s not exist", Str16ToStr8(procName).c_str());
return nullptr;
}
void SystemAbilityManager::SendSystemAbilityAddedMsg(int32_t systemAbilityId, const sptr<IRemoteObject>& remoteObject)
{
if (workHandler_ == nullptr) {
HILOGE("SendSystemAbilityAddedMsg work handler not initialized!");
return;
}
auto notifyAddedTask = [systemAbilityId, remoteObject, this]() {
FindSystemAbilityNotify(systemAbilityId, ADD_SYSTEM_ABILITY_TRANSACTION);
NotifySystemAbilityLoaded(systemAbilityId, remoteObject);
};
bool ret = workHandler_->PostTask(notifyAddedTask);
if (!ret) {
HILOGW("SendSystemAbilityAddedMsg PostTask failed!");
}
}
void SystemAbilityManager::SendSystemAbilityRemovedMsg(int32_t systemAbilityId)
{
if (workHandler_ == nullptr) {
HILOGE("SendSystemAbilityRemovedMsg work handler not initialized!");
return;
}
auto notifyRemovedTask = [systemAbilityId, this]() {
FindSystemAbilityNotify(systemAbilityId, REMOVE_SYSTEM_ABILITY_TRANSACTION);
};
bool ret = workHandler_->PostTask(notifyRemovedTask);
if (!ret) {
HILOGW("SendSystemAbilityRemovedMsg PostTask failed!");
}
}
void SystemAbilityManager::SendCheckLoadedMsg(int32_t systemAbilityId, const std::u16string& name,
const sptr<ISystemAbilityLoadCallback>& callback)
{
if (workHandler_ == nullptr) {
HILOGE("SendCheckLoadedMsg work handler not initialized!");
return;
}
auto delayTask = [systemAbilityId, name, callback, this]() {
HILOGI("SendCheckLoadedMsg handle for SA : %{public}d.", systemAbilityId);
if (CheckSystemAbility(systemAbilityId) != nullptr) {
HILOGI("SendCheckLoadedMsg SA : %{public}d loaded.", systemAbilityId);
return;
}
{
lock_guard<recursive_mutex> autoLock(onDemandLock_);
auto iter = startingAbilityMap_.find(systemAbilityId);
if (iter == startingAbilityMap_.end()) {
HILOGI("SendCheckLoadedMsg SA : %{public}d not in startingAbilityMap.", systemAbilityId);
return;
}
auto& abilityItem = iter->second;
for (auto& callbackItem : abilityItem.callbackList) {
if (callback->AsObject() == callbackItem.first->AsObject()) {
NotifySystemAbilityLoadFail(systemAbilityId, callbackItem.first);
RemoveStartingAbilityCallbackLocked(callbackItem);
abilityItem.callbackList.remove(callbackItem);
break;
}
}
if (abilityItem.callbackList.empty()) {
HILOGI("SendCheckLoadedMsg startingAbilityMap remove SA : %{public}d.", systemAbilityId);
startingAbilityMap_.erase(iter);
}
auto iterStarting = startingProcessMap_.find(name);
if (iterStarting != startingProcessMap_.end()) {
HILOGI("SendCheckLoadedMsg clean process:%{public}s", Str16ToStr8(name).c_str());
startingProcessMap_.erase(iterStarting);
}
}
(void)GetSystemProcess(name);
};
bool ret = workHandler_->PostTask(delayTask, ToString(systemAbilityId), CHECK_LOADED_DELAY_TIME);
HILOGI("SendCheckLoadedMsg PostTask name : %{public}d!, ret : %{public}s",
systemAbilityId, ret ? "success" : "failed");
}
void SystemAbilityManager::RemoveCheckLoadedMsg(int32_t systemAbilityId)
{
if (workHandler_ == nullptr) {
HILOGE("RemoveCheckLoadedMsg work handler not initialized!");
return;
}
workHandler_->RemoveTask(ToString(systemAbilityId));
}
void SystemAbilityManager::NotifySystemAbilityLoaded(int32_t systemAbilityId, const sptr<IRemoteObject>& remoteObject,
const sptr<ISystemAbilityLoadCallback>& callback)
{
if (callback == nullptr) {
HILOGE("NotifySystemAbilityLoaded callback null!");
return;
}
HILOGI("NotifySystemAbilityLoaded systemAbilityId : %{public}d", systemAbilityId);
callback->OnLoadSystemAbilitySuccess(systemAbilityId, remoteObject);
}
void SystemAbilityManager::NotifySystemAbilityLoaded(int32_t systemAbilityId, const sptr<IRemoteObject>& remoteObject)
{
lock_guard<recursive_mutex> autoLock(onDemandLock_);
auto iter = startingAbilityMap_.find(systemAbilityId);
if (iter == startingAbilityMap_.end()) {
return;
}
auto& abilityItem = iter->second;
for (auto& callbackItem : abilityItem.callbackList) {
NotifySystemAbilityLoaded(systemAbilityId, remoteObject, callbackItem.first);
RemoveStartingAbilityCallbackLocked(callbackItem);
}
startingAbilityMap_.erase(iter);
}
void SystemAbilityManager::NotifySystemAbilityLoadFail(int32_t systemAbilityId,
const sptr<ISystemAbilityLoadCallback>& callback)
{
if (callback == nullptr) {
HILOGE("NotifySystemAbilityLoadFail callback null!");
return;
}
HILOGI("NotifySystemAbilityLoadFailed systemAbilityId : %{public}d", systemAbilityId);
callback->OnLoadSystemAbilityFail(systemAbilityId);
}
int32_t SystemAbilityManager::StartDynamicSystemProcess(const std::u16string& name, int32_t systemAbilityId)
{
std::string strExtra = std::to_string(systemAbilityId);
auto extraArgv = strExtra.c_str();
auto result = ServiceControlWithExtra(Str16ToStr8(name).c_str(), START, &extraArgv, 1);
HILOGI("StartDynamicSystemProcess call ServiceControlWithExtra result:%{public}d!", result);
return (result == 0) ? ERR_OK : ERR_INVALID_VALUE;
}
int32_t SystemAbilityManager::StartingSystemProcess(const std::u16string& procName, int32_t systemAbilityId)
{
lock_guard<recursive_mutex> autoLock(onDemandLock_);
if (startingProcessMap_.count(procName) != 0) {
HILOGI("StartingSystemProcess process:%{public}s already starting!", Str16ToStr8(procName).c_str());
return ERR_OK;
}
auto iter = systemProcessMap_.find(procName);
if (iter != systemProcessMap_.end()) {
StartOnDemandAbility(systemAbilityId);
return ERR_OK;
}
// call init start process
int64_t begin = GetTickCount();
int32_t result = StartDynamicSystemProcess(procName, systemAbilityId);
if (result == ERR_OK) {
startingProcessMap_.emplace(procName, begin);
}
return result;
}
int32_t SystemAbilityManager::LoadSystemAbility(int32_t systemAbilityId,
const sptr<ISystemAbilityLoadCallback>& callback)
{
if (!CheckInputSysAbilityId(systemAbilityId) || callback == nullptr) {
HILOGW("LoadSystemAbility systemAbilityId or callback invalid!");
return ERR_INVALID_VALUE;
}
SaProfile saProfile;
bool ret = GetSaProfile(systemAbilityId, saProfile);
if (!ret) {
HILOGE("LoadSystemAbility systemAbilityId:%{public}d not supported!", systemAbilityId);
return ERR_INVALID_VALUE;
}
sptr<IRemoteObject> targetObject = CheckSystemAbility(systemAbilityId);
if (targetObject != nullptr) {
NotifySystemAbilityLoaded(systemAbilityId, targetObject, callback);
return ERR_OK;
}
int32_t result = ERR_INVALID_VALUE;
auto callingPid = IPCSkeleton::GetCallingPid();
{
lock_guard<recursive_mutex> autoLock(onDemandLock_);
auto& abilityItem = startingAbilityMap_[systemAbilityId];
for (const auto& itemCallback : abilityItem.callbackList) {
if (callback->AsObject() == itemCallback.first->AsObject()) {
HILOGI("LoadSystemAbility already existed callback object systemAbilityId:%{public}d", systemAbilityId);
return ERR_OK;
}
}
auto& count = callbackCountMap_[callingPid];
if (count >= MAX_SUBSCRIBE_COUNT) {
HILOGE("LoadSystemAbility pid:%{public}d overflow max callback count!", callingPid);
return ERR_PERMISSION_DENIED;
}
++count;
abilityItem.callbackList.emplace_back(callback, callingPid);
if (abilityCallbackDeath_ != nullptr) {
ret = callback->AsObject()->AddDeathRecipient(abilityCallbackDeath_);
HILOGI("LoadSystemAbility systemAbilityId:%{public}d AddDeathRecipient %{public}s",
systemAbilityId, ret ? "succeed" : "failed");
}
result = StartingSystemProcess(saProfile.process, systemAbilityId);
HILOGI("LoadSystemAbility systemAbilityId:%{public}d size : %{public}zu",
systemAbilityId, abilityItem.callbackList.size());
}
SendCheckLoadedMsg(systemAbilityId, saProfile.process, callback);
return result;
}
void SystemAbilityManager::RemoveStartingAbilityCallbackLocked(
std::pair<sptr<ISystemAbilityLoadCallback>, int32_t>& itemPair)
{
if (abilityCallbackDeath_ != nullptr) {
itemPair.first->AsObject()->RemoveDeathRecipient(abilityCallbackDeath_);
}
auto iterCount = callbackCountMap_.find(itemPair.second);
if (iterCount != callbackCountMap_.end()) {
--iterCount->second;
if (iterCount->second == 0) {
callbackCountMap_.erase(iterCount);
}
}
}
void SystemAbilityManager::RemoveStartingAbilityCallback(AbilityItem& abilityItem,
const sptr<IRemoteObject>& remoteObject)
{
auto& callbacks = abilityItem.callbackList;
auto iterCallback = callbacks.begin();
while (iterCallback != callbacks.end()) {
auto& callbackPair = *iterCallback;
if (callbackPair.first->AsObject() == remoteObject) {
RemoveStartingAbilityCallbackLocked(callbackPair);
iterCallback = callbacks.erase(iterCallback);
break;
} else {
++iterCallback;
}
}
}
void SystemAbilityManager::OnAbilityCallbackDied(const sptr<IRemoteObject>& remoteObject)
{
HILOGI("OnAbilityCallbackDied received remoteObject died message!");
lock_guard<recursive_mutex> autoLock(onDemandLock_);
auto iter = startingAbilityMap_.begin();
while (iter != startingAbilityMap_.end()) {
AbilityItem& abilityItem = iter->second;
RemoveStartingAbilityCallback(abilityItem, remoteObject);
if (abilityItem.callbackList.empty()) {
iter = startingAbilityMap_.erase(iter);
} else {
++iter;
}
}
}
std::string SystemAbilityManager::TransformDeviceId(const std::string& deviceId, int32_t type, bool isPrivate)
{
return isPrivate ? std::string() : deviceId;
}
std::string SystemAbilityManager::GetLocalNodeId()
{
return std::string();
}
} // namespace OHOS