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