1 /*
2 * Copyright (c) 2022-2023 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 "local_call_container.h"
17
18 #include "hilog_wrapper.h"
19 #include "ability_manager_client.h"
20 #include "os_account_manager_wrapper.h"
21
22 namespace OHOS {
23 namespace AbilityRuntime {
StartAbilityByCallInner(const Want & want,const std::shared_ptr<CallerCallBack> & callback,const sptr<IRemoteObject> & callerToken,int32_t accountId)24 int LocalCallContainer::StartAbilityByCallInner(const Want& want, const std::shared_ptr<CallerCallBack>& callback,
25 const sptr<IRemoteObject>& callerToken, int32_t accountId)
26 {
27 HILOG_DEBUG("start ability by call.");
28 if (callback == nullptr) {
29 HILOG_ERROR("callback is nullptr.");
30 return ERR_INVALID_VALUE;
31 }
32 if (want.GetElement().GetBundleName().empty() ||
33 want.GetElement().GetAbilityName().empty()) {
34 HILOG_ERROR("the element of want is empty.");
35 return ERR_INVALID_VALUE;
36 }
37 if (want.GetElement().GetDeviceID().empty()) {
38 HILOG_DEBUG("start ability by call, element:DeviceID is empty");
39 }
40 HILOG_DEBUG("start ability by call, element:%{public}s", want.GetElement().GetURI().c_str());
41 int32_t oriValidUserId = GetValidUserId(accountId);
42 AppExecFwk::ElementName element = want.GetElement();
43 std::shared_ptr<LocalCallRecord> localCallRecord;
44 if (!GetCallLocalRecord(element, localCallRecord, oriValidUserId)) {
45 localCallRecord = std::make_shared<LocalCallRecord>(element);
46 if (localCallRecord == nullptr) {
47 HILOG_ERROR("LocalCallContainer::StartAbilityByCallInner Create local call record failed");
48 return ERR_INVALID_VALUE;
49 }
50 localCallRecord->SetUserId(oriValidUserId);
51 HILOG_DEBUG("create local call record and set user id[%{public}d] to record", oriValidUserId);
52 }
53 localCallRecord->AddCaller(callback);
54 auto remote = localCallRecord->GetRemoteObject();
55 // already finish call request.
56 if (remote) {
57 HILOG_DEBUG("start ability by call, callback->InvokeCallBack(remote) begin");
58 callback->InvokeCallBack(remote);
59 HILOG_DEBUG("start ability by call, callback->InvokeCallBack(remote) end");
60 if (!want.GetBoolParam(Want::PARAM_RESV_CALL_TO_FOREGROUND, false)) {
61 return ERR_OK;
62 }
63 }
64 auto abilityClient = AAFwk::AbilityManagerClient::GetInstance();
65 if (abilityClient == nullptr) {
66 HILOG_ERROR("LocalCallContainer::StartAbilityByCallInner abilityClient is nullptr");
67 return ERR_INVALID_VALUE;
68 }
69 sptr<CallerConnection> connect = new (std::nothrow) CallerConnection();
70 if (connect == nullptr) {
71 HILOG_ERROR("LocalCallContainer::StartAbilityByCallInner Create local call connection failed");
72 return ERR_INVALID_VALUE;
73 }
74 connections_.emplace(connect);
75 connect->SetRecordAndContainer(localCallRecord, shared_from_this());
76 HILOG_DEBUG("LocalCallContainer::StartAbilityByCallInner connections_.size is %{public}zu", connections_.size());
77 auto retval = abilityClient->StartAbilityByCall(want, connect, callerToken, oriValidUserId);
78 if (retval != ERR_OK) {
79 ClearFailedCallConnection(callback);
80 }
81 return retval;
82 }
83
ReleaseCall(const std::shared_ptr<CallerCallBack> & callback)84 int LocalCallContainer::ReleaseCall(const std::shared_ptr<CallerCallBack>& callback)
85 {
86 HILOG_DEBUG("LocalCallContainer::ReleaseCall begin.");
87 if (callback == nullptr) {
88 HILOG_ERROR("LocalCallContainer::ReleaseCall input params is nullptr");
89 return ERR_INVALID_VALUE;
90 }
91 auto abilityClient = AAFwk::AbilityManagerClient::GetInstance();
92 if (abilityClient == nullptr) {
93 HILOG_ERROR("LocalCallContainer::ReleaseCall abilityClient is nullptr");
94 return ERR_INVALID_VALUE;
95 }
96 auto localCallRecord = callback->GetRecord();
97 if (localCallRecord == nullptr) {
98 HILOG_ERROR("LocalCallContainer::ReleaseCall abilityClient is nullptr");
99 return ERR_INVALID_VALUE;
100 }
101 localCallRecord->RemoveCaller(callback);
102 if (localCallRecord->IsExistCallBack()) {
103 // just release callback.
104 HILOG_DEBUG("LocalCallContainer::ReleaseCall, The callee has onther callers, just release this callback.");
105 return ERR_OK;
106 }
107 auto connect = iface_cast<CallerConnection>(localCallRecord->GetConnection());
108 if (connect == nullptr) {
109 HILOG_ERROR("LocalCallContainer::ReleaseCall connection conversion failed.");
110 return ERR_INVALID_VALUE;
111 }
112 int32_t retval = ERR_OK;
113 if (localCallRecord->IsSingletonRemote()) {
114 retval = RemoveSingletonCallLocalRecord(localCallRecord);
115 } else {
116 retval = RemoveMultipleCallLocalRecord(localCallRecord);
117 }
118
119 if (retval != ERR_OK) {
120 HILOG_ERROR("Remove call local record failed");
121 return retval;
122 }
123
124 connections_.erase(connect);
125 if (abilityClient->ReleaseCall(connect, localCallRecord->GetElementName()) != ERR_OK) {
126 HILOG_ERROR("ReleaseCall failed.");
127 return ERR_INVALID_VALUE;
128 }
129 HILOG_DEBUG("LocalCallContainer::ReleaseCall end.");
130 return ERR_OK;
131 }
132
ClearFailedCallConnection(const std::shared_ptr<CallerCallBack> & callback)133 void LocalCallContainer::ClearFailedCallConnection(const std::shared_ptr<CallerCallBack> &callback)
134 {
135 HILOG_DEBUG("LocalCallContainer::ClearFailedCallConnection called");
136 if (callback == nullptr) {
137 HILOG_ERROR("LocalCallContainer::ClearFailedCallConnection callback is nullptr");
138 return;
139 }
140
141 auto localCallRecord = callback->GetRecord();
142 if (localCallRecord == nullptr) {
143 HILOG_ERROR("LocalCallContainer::ClearFailedCallConnection localCallRecord is nullptr");
144 return;
145 }
146
147 auto connect = iface_cast<CallerConnection>(localCallRecord->GetConnection());
148 if (connect == nullptr) {
149 HILOG_ERROR("LocalCallContainer::ClearFailedCallConnection connection conversion failed.");
150 return;
151 }
152
153 connections_.erase(connect);
154 }
155
RemoveSingletonCallLocalRecord(const std::shared_ptr<LocalCallRecord> & record)156 int32_t LocalCallContainer::RemoveSingletonCallLocalRecord(const std::shared_ptr<LocalCallRecord> &record)
157 {
158 std::lock_guard<std::mutex> lock(mutex_);
159 if (record == nullptr) {
160 HILOG_ERROR("input params invalid value");
161 return ERR_INVALID_VALUE;
162 }
163
164 auto iterRecord = callProxyRecords_.find(record->GetElementName().GetURI());
165 if (iterRecord == callProxyRecords_.end()) {
166 HILOG_ERROR("release record in singleton not found.");
167 return ERR_INVALID_VALUE;
168 }
169
170 iterRecord->second.erase(record);
171 if (iterRecord->second.empty()) {
172 callProxyRecords_.erase(iterRecord);
173 }
174
175 return ERR_OK;
176 }
177
RemoveMultipleCallLocalRecord(const std::shared_ptr<LocalCallRecord> & record)178 int32_t LocalCallContainer::RemoveMultipleCallLocalRecord(const std::shared_ptr<LocalCallRecord> &record)
179 {
180 if (record == nullptr) {
181 HILOG_ERROR("input params invalid value");
182 return ERR_INVALID_VALUE;
183 }
184
185 std::lock_guard<std::mutex> lock(multipleMutex_);
186 auto iterRecord = multipleCallProxyRecords_.find(record->GetElementName().GetURI());
187 if (iterRecord == multipleCallProxyRecords_.end()) {
188 HILOG_ERROR("release record in multiple not found.");
189 return ERR_INVALID_VALUE;
190 }
191
192 iterRecord->second.erase(record);
193 if (iterRecord->second.empty()) {
194 multipleCallProxyRecords_.erase(iterRecord);
195 }
196
197 return ERR_OK;
198 }
199
IsCallBackCalled(const std::vector<std::shared_ptr<CallerCallBack>> & callers) const200 bool LocalCallContainer::IsCallBackCalled(const std::vector<std::shared_ptr<CallerCallBack>> &callers) const
201 {
202 for (auto& callBack : callers) {
203 if (callBack != nullptr && !callBack->IsCallBack()) {
204 HILOG_INFO("%{public}s call back is not called.", __func__);
205 return false;
206 }
207 }
208
209 return true;
210 }
211
DumpCalls(std::vector<std::string> & info)212 void LocalCallContainer::DumpCalls(std::vector<std::string>& info)
213 {
214 HILOG_DEBUG("LocalCallContainer::DumpCalls called.");
215 info.emplace_back(" caller connections:");
216 std::lock_guard<std::mutex> lock(mutex_);
217 for (auto &item : callProxyRecords_) {
218 for (auto &itemCall : item.second) {
219 std::string tempstr = " LocalCallRecord";
220 tempstr += " ID #" + std::to_string(itemCall->GetRecordId()) + "\n";
221 tempstr += " callee";
222 tempstr += " uri[" + item.first + "]" + "\n";
223 tempstr += " callers #" + std::to_string(itemCall->GetCallers().size());
224 if (IsCallBackCalled(itemCall->GetCallers())) {
225 HILOG_INFO("%{public}s state is REQUESTEND.", __func__);
226 tempstr += " state #REQUESTEND";
227 } else {
228 HILOG_INFO("%{public}s state is REQUESTING.", __func__);
229 tempstr += " state #REQUESTING";
230 }
231 info.emplace_back(tempstr);
232 }
233 }
234 return;
235 }
236
GetCallLocalRecord(const AppExecFwk::ElementName & elementName,std::shared_ptr<LocalCallRecord> & localCallRecord,int32_t accountId)237 bool LocalCallContainer::GetCallLocalRecord(
238 const AppExecFwk::ElementName& elementName, std::shared_ptr<LocalCallRecord>& localCallRecord, int32_t accountId)
239 {
240 std::lock_guard<std::mutex> lock(mutex_);
241 HILOG_DEBUG("Get call local record by %{public}s and id %{public}d", elementName.GetURI().c_str(), accountId);
242 for (auto pair : callProxyRecords_) {
243 AppExecFwk::ElementName callElement;
244 if (!callElement.ParseURI(pair.first)) {
245 HILOG_ERROR("Parse uri to elementName failed, elementName uri: %{private}s", pair.first.c_str());
246 continue;
247 }
248 // elementName in callProxyRecords_ has moduleName (sometimes not empty),
249 // but the moduleName of input param elementName is usually empty.
250 callElement.SetModuleName("");
251 if ((pair.first != elementName.GetURI() && callElement.GetURI() != elementName.GetURI())) {
252 continue;
253 }
254
255 for (auto &itemCall : pair.second) {
256 if (itemCall != nullptr && itemCall->GetUserId() == accountId) {
257 localCallRecord = itemCall;
258 return true;
259 }
260 }
261 }
262 return false;
263 }
264
OnCallStubDied(const wptr<IRemoteObject> & remote)265 void LocalCallContainer::OnCallStubDied(const wptr<IRemoteObject>& remote)
266 {
267 auto diedRemote = remote.promote();
268 auto isExist = [&diedRemote](auto& record) {
269 return record->IsSameObject(diedRemote);
270 };
271
272 {
273 std::lock_guard<std::mutex> lock(mutex_);
274 for (auto &item : callProxyRecords_) {
275 auto iter = std::find_if(item.second.begin(), item.second.end(), isExist);
276 if (iter == item.second.end()) {
277 continue;
278 }
279 HILOG_DEBUG("LocalCallContainer::OnCallStubDied singleton key[%{public}s]. notify died event",
280 item.first.c_str());
281 (*iter)->OnCallStubDied(remote);
282 item.second.erase(iter);
283 if (item.second.empty()) {
284 HILOG_DEBUG("LocalCallContainer::OnCallStubDied singleton key[%{public}s] empty.", item.first.c_str());
285 callProxyRecords_.erase(item.first);
286 break;
287 }
288 }
289 }
290
291 std::lock_guard<std::mutex> lock(multipleMutex_);
292 for (auto &item : multipleCallProxyRecords_) {
293 HILOG_DEBUG("LocalCallContainer::OnCallStubDied multiple key[%{public}s].", item.first.c_str());
294 auto iterMultiple = find_if(item.second.begin(), item.second.end(), isExist);
295 if (iterMultiple == item.second.end()) {
296 continue;
297 }
298 HILOG_DEBUG("LocalCallContainer::OnCallStubDied multiple key[%{public}s]. notify died event",
299 item.first.c_str());
300 (*iterMultiple)->OnCallStubDied(remote);
301 item.second.erase(iterMultiple);
302 if (item.second.empty()) {
303 HILOG_DEBUG("LocalCallContainer::OnCallStubDied multiple key[%{public}s] empty.", item.first.c_str());
304 multipleCallProxyRecords_.erase(item.first);
305 break;
306 }
307 }
308 HILOG_DEBUG("LocalCallContainer::OnCallStubDied end.");
309 }
310
SetCallLocalRecord(const AppExecFwk::ElementName & element,const std::shared_ptr<LocalCallRecord> & localCallRecord)311 void LocalCallContainer::SetCallLocalRecord(
312 const AppExecFwk::ElementName& element, const std::shared_ptr<LocalCallRecord> &localCallRecord)
313 {
314 HILOG_DEBUG("LocalCallContainer::SetCallLocalRecord called uri is %{private}s.", element.GetURI().c_str());
315 const std::string strKey = element.GetURI();
316 std::lock_guard<std::mutex> lock(mutex_);
317 auto iter = callProxyRecords_.find(strKey);
318 if (iter == callProxyRecords_.end()) {
319 std::set<std::shared_ptr<LocalCallRecord>> records = { localCallRecord };
320 callProxyRecords_.emplace(strKey, records);
321 return;
322 }
323
324 iter->second.emplace(localCallRecord);
325 }
326
SetMultipleCallLocalRecord(const AppExecFwk::ElementName & element,const std::shared_ptr<LocalCallRecord> & localCallRecord)327 void LocalCallContainer::SetMultipleCallLocalRecord(
328 const AppExecFwk::ElementName& element, const std::shared_ptr<LocalCallRecord> &localCallRecord)
329 {
330 HILOG_DEBUG("LocalCallContainer::SetMultipleCallLocalRecord called uri is %{private}s.", element.GetURI().c_str());
331 const std::string strKey = element.GetURI();
332 std::lock_guard<std::mutex> lock(multipleMutex_);
333 auto iter = multipleCallProxyRecords_.find(strKey);
334 if (iter == multipleCallProxyRecords_.end()) {
335 std::set<std::shared_ptr<LocalCallRecord>> records = { localCallRecord };
336 multipleCallProxyRecords_.emplace(strKey, records);
337 return;
338 }
339
340 iter->second.emplace(localCallRecord);
341 }
342
SetRecordAndContainer(const std::shared_ptr<LocalCallRecord> & localCallRecord,const std::weak_ptr<LocalCallContainer> & container)343 void CallerConnection::SetRecordAndContainer(const std::shared_ptr<LocalCallRecord> &localCallRecord,
344 const std::weak_ptr<LocalCallContainer> &container)
345 {
346 if (localCallRecord == nullptr) {
347 HILOG_DEBUG("CallerConnection::SetRecordAndContainer input param is nullptr.");
348 return;
349 }
350 localCallRecord_ = localCallRecord;
351 container_ = container;
352 localCallRecord_->SetConnection(this->AsObject());
353 }
354
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int code)355 void CallerConnection::OnAbilityConnectDone(
356 const AppExecFwk::ElementName &element, const sptr<IRemoteObject> &remoteObject, int code)
357 {
358 HILOG_DEBUG("CallerConnection::OnAbilityConnectDone start %{public}s .", element.GetURI().c_str());
359 auto container = container_.lock();
360 if (container == nullptr || localCallRecord_ == nullptr) {
361 HILOG_ERROR("CallerConnection::OnAbilityConnectDone container or record is nullptr.");
362 return;
363 }
364
365 const bool isSingleton = (code == static_cast<int32_t>(AppExecFwk::LaunchMode::SINGLETON));
366 localCallRecord_->SetIsSingleton(isSingleton);
367
368 auto callRecipient = new (std::nothrow) CallRecipient(
369 std::bind(&LocalCallContainer::OnCallStubDied, container, std::placeholders::_1));
370 localCallRecord_->SetRemoteObject(remoteObject, callRecipient);
371
372 if (isSingleton) {
373 container->SetCallLocalRecord(element, localCallRecord_);
374 } else {
375 container->SetMultipleCallLocalRecord(element, localCallRecord_);
376 }
377
378 localCallRecord_->InvokeCallBack();
379 HILOG_DEBUG("CallerConnection::OnAbilityConnectDone end. code:%{public}d.", code);
380 return;
381 }
382
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int code)383 void CallerConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int code)
384 {
385 HILOG_DEBUG("CallerConnection::OnAbilityDisconnectDone start %{public}s %{public}d.",
386 element.GetURI().c_str(), code);
387 }
388
OnRemoteStateChanged(const AppExecFwk::ElementName & element,int32_t abilityState)389 void CallerConnection::OnRemoteStateChanged(const AppExecFwk::ElementName &element, int32_t abilityState)
390 {
391 HILOG_DEBUG("CallerConnection::OnRemoteStateChanged start %{public}s .", element.GetURI().c_str());
392 if (localCallRecord_ == nullptr) {
393 HILOG_DEBUG("local call record is nullptr.");
394 return;
395 }
396
397 localCallRecord_->NotifyRemoteStateChanged(abilityState);
398
399 HILOG_DEBUG("CallerConnection::OnRemoteStateChanged end. abilityState:%{public}d.", abilityState);
400 return;
401 }
402
GetCurrentUserId()403 int32_t LocalCallContainer::GetCurrentUserId()
404 {
405 if (currentUserId_ == DEFAULT_INVAL_VALUE) {
406 auto osAccount = DelayedSingleton<AppExecFwk::OsAccountManagerWrapper>::GetInstance();
407 if (osAccount == nullptr) {
408 HILOG_ERROR("LocalCallContainer::GetCurrentUserId get osAccount is nullptr.");
409 return DEFAULT_INVAL_VALUE;
410 }
411
412 osAccount->GetOsAccountLocalIdFromProcess(currentUserId_);
413 HILOG_DEBUG("LocalCallContainer::GetCurrentUserId called. %{public}d", currentUserId_);
414 }
415
416 return currentUserId_;
417 }
418
GetValidUserId(int32_t accountId)419 int32_t LocalCallContainer::GetValidUserId(int32_t accountId)
420 {
421 HILOG_DEBUG("LocalCallContainer::GetValidUserId is %{public}d", accountId);
422 if (accountId > 0 && accountId != GetCurrentUserId()) {
423 return accountId;
424 }
425
426 return DEFAULT_INVAL_VALUE;
427 }
428 } // namespace AbilityRuntime
429 } // namespace OHOS
430