• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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