1 /*
2 * Copyright (c) 2022 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 "call_container.h"
17
18 #include "hilog_wrapper.h"
19 #include "ability_manager_errors.h"
20 #include "ability_connect_callback_stub.h"
21 #include "ability_util.h"
22 #include "ability_manager_service.h"
23
24 namespace OHOS {
25 namespace AAFwk {
CallContainer()26 CallContainer::CallContainer()
27 {}
28
~CallContainer()29 CallContainer::~CallContainer()
30 {
31 std::for_each(deathRecipientMap_.begin(),
32 deathRecipientMap_.end(),
33 [&](RecipientMapType::reference recipient) {
34 recipient.first->RemoveDeathRecipient(recipient.second);
35 });
36
37 deathRecipientMap_.clear();
38 callRecordMap_.clear();
39 }
40
AddCallRecord(const sptr<IAbilityConnection> & connect,const std::shared_ptr<CallRecord> & callRecord)41 void CallContainer::AddCallRecord(const sptr<IAbilityConnection> & connect,
42 const std::shared_ptr<CallRecord>& callRecord)
43 {
44 CHECK_POINTER(callRecord);
45 CHECK_POINTER(connect);
46 CHECK_POINTER(connect->AsObject());
47
48 auto iter = callRecordMap_.find(connect->AsObject());
49 if (iter != callRecordMap_.end()) {
50 RemoveConnectDeathRecipient(connect);
51 callRecordMap_.erase(callRecordMap_.find(connect->AsObject()));
52 }
53
54 AddConnectDeathRecipient(connect);
55 callRecord->SetConCallBack(connect);
56 callRecordMap_.emplace(connect->AsObject(), callRecord);
57
58 HILOG_DEBUG("Add call record to callcontainer, target: %{public}s",
59 callRecord->GetTargetServiceName().GetURI().c_str());
60 }
61
GetCallRecord(const sptr<IAbilityConnection> & connect) const62 std::shared_ptr<CallRecord> CallContainer::GetCallRecord(const sptr<IAbilityConnection> & connect) const
63 {
64 CHECK_POINTER_AND_RETURN(connect, nullptr);
65 CHECK_POINTER_AND_RETURN(connect->AsObject(), nullptr);
66
67 auto mapIter = callRecordMap_.find(connect->AsObject());
68 if (mapIter != callRecordMap_.end()) {
69 return mapIter->second;
70 }
71
72 return nullptr;
73 }
74
RemoveCallRecord(const sptr<IAbilityConnection> & connect)75 bool CallContainer::RemoveCallRecord(const sptr<IAbilityConnection> & connect)
76 {
77 HILOG_DEBUG("call container release call record by callback.");
78 CHECK_POINTER_AND_RETURN(connect, false);
79 CHECK_POINTER_AND_RETURN(connect->AsObject(), false);
80
81 auto iter = callRecordMap_.find(connect->AsObject());
82 if (iter != callRecordMap_.end()) {
83 auto callrecord = iter->second;
84 if (callrecord) {
85 callrecord->SchedulerDisconnectDone();
86 }
87 RemoveConnectDeathRecipient(connect);
88 callRecordMap_.erase(callRecordMap_.find(connect->AsObject()));
89 HILOG_DEBUG("remove call record is success.");
90 return true;
91 }
92
93 if (callRecordMap_.empty()) {
94 // notify soft resouce service.
95 HILOG_DEBUG("this ability has no callrecord.");
96 }
97
98 HILOG_WARN("remove call record is not exist.");
99 return false;
100 }
101
OnConnectionDied(const wptr<IRemoteObject> & remote)102 void CallContainer::OnConnectionDied(const wptr<IRemoteObject> &remote)
103 {
104 HILOG_WARN("Call back is died.");
105 auto object = remote.promote();
106 CHECK_POINTER(object);
107
108 std::shared_ptr<CallRecord> callRecord = nullptr;
109 auto mapIter = callRecordMap_.find(object);
110 if (mapIter != callRecordMap_.end()) {
111 callRecord = mapIter->second;
112 }
113
114 auto abilityManagerService = DelayedSingleton<AbilityManagerService>::GetInstance();
115 CHECK_POINTER(abilityManagerService);
116 auto handler = abilityManagerService->GetTaskHandler();
117 CHECK_POINTER(handler);
118 auto task = [abilityManagerService, callRecord]() {
119 abilityManagerService->OnCallConnectDied(callRecord);
120 };
121 handler->SubmitTask(task);
122 }
123
CallRequestDone(const sptr<IRemoteObject> & callStub)124 bool CallContainer::CallRequestDone(const sptr<IRemoteObject> &callStub)
125 {
126 HILOG_INFO("Call Request Done start.");
127
128 CHECK_POINTER_AND_RETURN(callStub, false);
129
130 std::for_each(callRecordMap_.begin(),
131 callRecordMap_.end(),
132 [&callStub](CallMapType::reference service) {
133 std::shared_ptr<CallRecord> callRecord = service.second;
134 if (callRecord && callRecord->IsCallState(CallState::REQUESTING)) {
135 callRecord->SetCallStub(callStub);
136 callRecord->SchedulerConnectDone();
137 }
138 });
139
140 HILOG_INFO("Call Request Done end.");
141 return true;
142 }
143
Dump(std::vector<std::string> & info) const144 void CallContainer::Dump(std::vector<std::string> &info) const
145 {
146 HILOG_INFO("Dump call records.");
147 for (const auto &iter : callRecordMap_) {
148 auto callRecord = iter.second;
149 if (callRecord) {
150 callRecord->Dump(info);
151 }
152 }
153 }
154
IsNeedToCallRequest() const155 bool CallContainer::IsNeedToCallRequest() const
156 {
157 for (const auto &iter : callRecordMap_) {
158 auto callRecord = iter.second;
159 if (callRecord && !callRecord->IsCallState(CallState::REQUESTED)) {
160 return true;
161 }
162 }
163 return false;
164 }
165
AddConnectDeathRecipient(const sptr<IAbilityConnection> & connect)166 void CallContainer::AddConnectDeathRecipient(const sptr<IAbilityConnection> &connect)
167 {
168 CHECK_POINTER(connect);
169 CHECK_POINTER(connect->AsObject());
170 auto it = deathRecipientMap_.find(connect->AsObject());
171 if (it != deathRecipientMap_.end()) {
172 HILOG_ERROR("This death recipient has been added.");
173 return;
174 } else {
175 std::weak_ptr<CallContainer> thisWeakPtr(shared_from_this());
176 sptr<IRemoteObject::DeathRecipient> deathRecipient =
177 new AbilityConnectCallbackRecipient([thisWeakPtr](const wptr<IRemoteObject> &remote) {
178 auto callContainer = thisWeakPtr.lock();
179 if (callContainer) {
180 callContainer->OnConnectionDied(remote);
181 }
182 });
183 if (!connect->AsObject()->AddDeathRecipient(deathRecipient)) {
184 HILOG_ERROR("AddDeathRecipient failed.");
185 }
186 deathRecipientMap_.emplace(connect->AsObject(), deathRecipient);
187 }
188 }
189
RemoveConnectDeathRecipient(const sptr<IAbilityConnection> & connect)190 void CallContainer::RemoveConnectDeathRecipient(const sptr<IAbilityConnection> &connect)
191 {
192 CHECK_POINTER(connect);
193 CHECK_POINTER(connect->AsObject());
194 auto it = deathRecipientMap_.find(connect->AsObject());
195 if (it != deathRecipientMap_.end()) {
196 it->first->RemoveDeathRecipient(it->second);
197 deathRecipientMap_.erase(it);
198 return;
199 }
200 }
201
IsExistConnection(const sptr<IAbilityConnection> & connect)202 bool CallContainer::IsExistConnection(const sptr<IAbilityConnection> &connect)
203 {
204 return callRecordMap_.find(connect->AsObject()) != callRecordMap_.end();
205 }
206 } // namespace AAFwk
207 } // namesspace OHOS
208