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