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