/* * Copyright (c) 2020 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 "ability_service_manager.h" #include #include "ability_kit_command.h" #include "ability_service_interface.h" #include "abilityms_client.h" #include "ohos_errno.h" #include "rpc_errno.h" #include "securec.h" #include "utils.h" #include "want.h" namespace OHOS { namespace { constexpr static uint16_t STORE_LIST_CAPACITY = 10240; } AbilityServiceManager::~AbilityServiceManager() { for (const auto &storeArgs : storeList_) { if (storeArgs == nullptr) { continue; } if (storeArgs->sid != nullptr) { delete storeArgs->sid; } delete storeArgs; } storeList_.clear(); } int AbilityServiceManager::ConnectAbility(const Want &want, const IAbilityConnection &conn, uint64_t token, void *storeArg) { if (conn.OnAbilityDisconnectDone == nullptr || conn.OnAbilityConnectDone == nullptr) { HILOG_INFO(HILOG_MODULE_APP, "IAbilityConnection callback func is null"); return ERR_INVALID_PARAM; } StoreArgs *storeArgs = AddStoreArgs(conn, storeArg); if (storeArgs == nullptr) { return ERR_INVALID_PARAM; } AbilityMsClient::GetInstance().Initialize(); objectStub_.func = ConnectAbilityCallBack; objectStub_.args = (void*)storeArgs; objectStub_.isRemote = false; storeArgs->sid->handle = IPC_INVALID_HANDLE; storeArgs->sid->token = SERVICE_TYPE_ANONYMOUS; storeArgs->sid->cookie = reinterpret_cast(&objectStub_); int32_t result = AbilityMsClient::GetInstance().ScheduleAms(&want, token, storeArgs->sid, CONNECT_ABILITY); if (result != EC_SUCCESS) { RemoveStoreArgs(nullptr, storeArgs); delete storeArgs->sid; delete storeArgs; } return result; } int AbilityServiceManager::DisconnectAbility(const IAbilityConnection &conn, uint64_t token) { StoreArgs *storeArgs = RemoveStoreArgs(&conn, nullptr); if (storeArgs == nullptr) { HILOG_INFO(HILOG_MODULE_APP, "no need to disconnect"); return ERR_INVALID_PARAM; } int result = AbilityMsClient::GetInstance().ScheduleAms(nullptr, token, storeArgs->sid, DISCONNECT_ABILITY); ClearStore(storeArgs); return result; } StoreArgs *AbilityServiceManager::AddStoreArgs(const IAbilityConnection &conn, void *storeArg) { std::lock_guard lock(mutex_); if (GetStoreArgs(conn) != nullptr) { HILOG_ERROR(HILOG_MODULE_APP, "func has already used"); return nullptr; } if (storeList_.size() >= STORE_LIST_CAPACITY) { HILOG_ERROR(HILOG_MODULE_APP, "can not add more storeArgs, capacity overflow"); return nullptr; } StoreArgs *storeArgs = new StoreArgs(); storeArgs->conn = &conn; storeArgs->storeArg = storeArg; storeArgs->sid = new SvcIdentity(); storeList_.emplace_back(storeArgs); return storeArgs; } StoreArgs *AbilityServiceManager::GetStoreArgs(const IAbilityConnection &conn) const { for (const auto storeArgs : storeList_) { if (storeArgs->conn == &conn) { return storeArgs; } } return nullptr; } StoreArgs *AbilityServiceManager::RemoveStoreArgs(const IAbilityConnection *conn, StoreArgs *storeArgs) { std::lock_guard lock(mutex_); if (storeArgs == nullptr) { storeArgs = GetStoreArgs(*conn); } storeList_.remove(storeArgs); return storeArgs; } int32_t AbilityServiceManager::ConnectAbilityCallBack(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option) { // param check StoreArgs *storeArgs = static_cast(option.args); if (storeArgs == nullptr || storeArgs->conn == nullptr || storeArgs->conn->OnAbilityConnectDone == nullptr || storeArgs->conn->OnAbilityDisconnectDone == nullptr) { HILOG_ERROR(HILOG_MODULE_APP, "storeArgs or callback func or ipcMsg is null"); AbilityServiceManager::GetInstance().RemoveStoreArgs(nullptr, storeArgs); ClearStore(storeArgs); return ERR_INVALID_PARAM; } int resultCode = (code != SCHEDULER_ABILITY_CONNECT_FAIL) ? 0 : -1; SvcIdentity *serviceSid = nullptr; SvcIdentity svc; if (code == SCHEDULER_ABILITY_CONNECT) { // parse service sid bool ret = ReadRemoteObject(data, &svc); if (ret) { serviceSid = &svc; } } if ((code == SCHEDULER_ABILITY_CONNECT) && (serviceSid == nullptr)) { resultCode = -1; } // parse element ElementName elementName = { nullptr }; if (!DeserializeElement(&elementName, data)) { resultCode = -1; } if (code == SCHEDULER_ABILITY_DISCONNECT) { storeArgs->conn->OnAbilityDisconnectDone(&elementName, resultCode, storeArgs->storeArg); } else { storeArgs->conn->OnAbilityConnectDone(&elementName, serviceSid, resultCode, storeArgs->storeArg); } if (code != SCHEDULER_ABILITY_CONNECT || resultCode == -1) { AbilityServiceManager::GetInstance().RemoveStoreArgs(nullptr, storeArgs); ClearStore(storeArgs); } ClearElement(&elementName); return ERR_NONE; } void AbilityServiceManager::ClearStore(StoreArgs *storeArgs) { if ((storeArgs == nullptr) || (storeArgs->sid == nullptr)) { HILOG_INFO(HILOG_MODULE_APP, "no need to clear storeArgs"); return; } delete storeArgs->sid; delete storeArgs; } } // namespace OHOS