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