1 /*
2 * Copyright (c) 2020 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ability_service_manager.h"
17
18 #include <log.h>
19
20 #include "ability_kit_command.h"
21 #include "ability_service_interface.h"
22 #include "abilityms_client.h"
23 #include "ohos_errno.h"
24 #include "rpc_errno.h"
25 #include "securec.h"
26 #include "utils.h"
27 #include "want.h"
28
29 namespace OHOS {
30
31 namespace {
32 constexpr static uint16_t STORE_LIST_CAPACITY = 10240;
33 }
34
~AbilityServiceManager()35 AbilityServiceManager::~AbilityServiceManager()
36 {
37 for (const auto &storeArgs : storeList_) {
38 if (storeArgs == nullptr) {
39 continue;
40 }
41 if (storeArgs->sid != nullptr) {
42 delete storeArgs->sid;
43 }
44 delete storeArgs;
45 }
46 storeList_.clear();
47 }
48
ConnectAbility(const Want & want,const IAbilityConnection & conn,uint64_t token,void * storeArg)49 int AbilityServiceManager::ConnectAbility(const Want &want, const IAbilityConnection &conn,
50 uint64_t token, void *storeArg)
51 {
52 if (conn.OnAbilityDisconnectDone == nullptr || conn.OnAbilityConnectDone == nullptr) {
53 HILOG_INFO(HILOG_MODULE_APP, "IAbilityConnection callback func is null");
54 return ERR_INVALID_PARAM;
55 }
56
57 StoreArgs *storeArgs = AddStoreArgs(conn, storeArg);
58 if (storeArgs == nullptr) {
59 return ERR_INVALID_PARAM;
60 }
61 AbilityMsClient::GetInstance().Initialize();
62
63 objectStub_.func = ConnectAbilityCallBack;
64 objectStub_.args = (void*)storeArgs;
65 objectStub_.isRemote = false;
66 storeArgs->sid->handle = IPC_INVALID_HANDLE;
67 storeArgs->sid->token = SERVICE_TYPE_ANONYMOUS;
68 storeArgs->sid->cookie = reinterpret_cast<uintptr_t>(&objectStub_);
69
70 int32_t result = AbilityMsClient::GetInstance().ScheduleAms(&want, token, storeArgs->sid, CONNECT_ABILITY);
71 if (result != EC_SUCCESS) {
72 RemoveStoreArgs(nullptr, storeArgs);
73 delete storeArgs->sid;
74 delete storeArgs;
75 }
76 return result;
77 }
78
DisconnectAbility(const IAbilityConnection & conn,uint64_t token)79 int AbilityServiceManager::DisconnectAbility(const IAbilityConnection &conn, uint64_t token)
80 {
81 StoreArgs *storeArgs = RemoveStoreArgs(&conn, nullptr);
82 if (storeArgs == nullptr) {
83 HILOG_INFO(HILOG_MODULE_APP, "no need to disconnect");
84 return ERR_INVALID_PARAM;
85 }
86 int result = AbilityMsClient::GetInstance().ScheduleAms(nullptr, token, storeArgs->sid, DISCONNECT_ABILITY);
87
88 ClearStore(storeArgs);
89 return result;
90 }
91
AddStoreArgs(const IAbilityConnection & conn,void * storeArg)92 StoreArgs *AbilityServiceManager::AddStoreArgs(const IAbilityConnection &conn, void *storeArg)
93 {
94 std::lock_guard<std::mutex> lock(mutex_);
95 if (GetStoreArgs(conn) != nullptr) {
96 HILOG_ERROR(HILOG_MODULE_APP, "func has already used");
97 return nullptr;
98 }
99 if (storeList_.size() >= STORE_LIST_CAPACITY) {
100 HILOG_ERROR(HILOG_MODULE_APP, "can not add more storeArgs, capacity overflow");
101 return nullptr;
102 }
103 StoreArgs *storeArgs = new StoreArgs();
104 storeArgs->conn = &conn;
105 storeArgs->storeArg = storeArg;
106 storeArgs->sid = new SvcIdentity();
107 storeList_.emplace_back(storeArgs);
108
109 return storeArgs;
110 }
111
GetStoreArgs(const IAbilityConnection & conn) const112 StoreArgs *AbilityServiceManager::GetStoreArgs(const IAbilityConnection &conn) const
113 {
114 for (const auto storeArgs : storeList_) {
115 if (storeArgs->conn == &conn) {
116 return storeArgs;
117 }
118 }
119 return nullptr;
120 }
121
RemoveStoreArgs(const IAbilityConnection * conn,StoreArgs * storeArgs)122 StoreArgs *AbilityServiceManager::RemoveStoreArgs(const IAbilityConnection *conn, StoreArgs *storeArgs)
123 {
124 std::lock_guard<std::mutex> lock(mutex_);
125 if (storeArgs == nullptr) {
126 storeArgs = GetStoreArgs(*conn);
127 }
128 storeList_.remove(storeArgs);
129
130 return storeArgs;
131 }
132
ConnectAbilityCallBack(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option)133 int32_t AbilityServiceManager::ConnectAbilityCallBack(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
134 {
135 // param check
136 StoreArgs *storeArgs = static_cast<StoreArgs *>(option.args);
137 if (storeArgs == nullptr || storeArgs->conn == nullptr ||
138 storeArgs->conn->OnAbilityConnectDone == nullptr || storeArgs->conn->OnAbilityDisconnectDone == nullptr) {
139 HILOG_ERROR(HILOG_MODULE_APP, "storeArgs or callback func or ipcMsg is null");
140 AbilityServiceManager::GetInstance().RemoveStoreArgs(nullptr, storeArgs);
141 ClearStore(storeArgs);
142 return ERR_INVALID_PARAM;
143 }
144
145 int resultCode = (code != SCHEDULER_ABILITY_CONNECT_FAIL) ? 0 : -1;
146
147 SvcIdentity *serviceSid = nullptr;
148 SvcIdentity svc;
149 if (code == SCHEDULER_ABILITY_CONNECT) {
150 // parse service sid
151 bool ret = ReadRemoteObject(data, &svc);
152 if (ret) {
153 serviceSid = &svc;
154 }
155 }
156
157 if ((code == SCHEDULER_ABILITY_CONNECT) && (serviceSid == nullptr)) {
158 resultCode = -1;
159 }
160 // parse element
161 ElementName elementName = { nullptr };
162 if (!DeserializeElement(&elementName, data)) {
163 resultCode = -1;
164 }
165 if (code == SCHEDULER_ABILITY_DISCONNECT) {
166 storeArgs->conn->OnAbilityDisconnectDone(&elementName, resultCode, storeArgs->storeArg);
167 } else {
168 storeArgs->conn->OnAbilityConnectDone(&elementName, serviceSid, resultCode, storeArgs->storeArg);
169 }
170 if (code != SCHEDULER_ABILITY_CONNECT || resultCode == -1) {
171 AbilityServiceManager::GetInstance().RemoveStoreArgs(nullptr, storeArgs);
172 ClearStore(storeArgs);
173 }
174
175 ClearElement(&elementName);
176 return ERR_NONE;
177 }
178
ClearStore(StoreArgs * storeArgs)179 void AbilityServiceManager::ClearStore(StoreArgs *storeArgs)
180 {
181 if ((storeArgs == nullptr) || (storeArgs->sid == nullptr)) {
182 HILOG_INFO(HILOG_MODULE_APP, "no need to clear storeArgs");
183 return;
184 }
185 delete storeArgs->sid;
186 delete storeArgs;
187 }
188 } // namespace OHOS
189