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 "accessible_ability_connection.h"
17 
18 #include <hitrace_meter.h>
19 
20 #include "ability_manager_client.h"
21 #include "accessible_ability_manager_service.h"
22 #include "hilog_wrapper.h"
23 #include "utils.h"
24 
25 namespace OHOS {
26 namespace Accessibility {
AccessibleAbilityConnection(int32_t accountId,int32_t connectionId,AccessibilityAbilityInfo & abilityInfo)27 AccessibleAbilityConnection::AccessibleAbilityConnection(int32_t accountId, int32_t connectionId,
28     AccessibilityAbilityInfo &abilityInfo)
29     : accountId_(accountId), connectionId_(connectionId), abilityInfo_(abilityInfo)
30 {
31     eventHandler_ = std::make_shared<AppExecFwk::EventHandler>(
32         Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner());
33 }
34 
~AccessibleAbilityConnection()35 AccessibleAbilityConnection::~AccessibleAbilityConnection()
36 {
37     HILOG_DEBUG();
38     if (abilityClient_ && abilityClient_->AsObject()) {
39         abilityClient_->AsObject()->RemoveDeathRecipient(deathRecipient_);
40         abilityClient_ = nullptr;
41     }
42 }
43 
OnAbilityConnectDone(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject,int32_t resultCode)44 void AccessibleAbilityConnection::OnAbilityConnectDone(const AppExecFwk::ElementName &element,
45     const sptr<IRemoteObject> &remoteObject, int32_t resultCode)
46 {
47     HILOG_INFO("ResultCode is %{public}d", resultCode);
48     if (!eventHandler_) {
49         HILOG_ERROR("eventHandler_ is nullptr.");
50         auto accountData = Singleton<AccessibleAbilityManagerService>::GetInstance().GetAccountData(accountId_);
51         if (accountData != nullptr) {
52             accountData->RemoveConnectingA11yAbility(Utils::GetUri(element));
53             return;
54         }
55         return;
56     }
57 
58     int32_t accountId = accountId_;
59     eventHandler_->PostTask([accountId, element, remoteObject, resultCode]() {
60         FinishAsyncTrace(HITRACE_TAG_ACCESSIBILITY_MANAGER, "AccessibleAbilityConnect",
61             static_cast<int32_t>(TraceTaskId::ACCESSIBLE_ABILITY_CONNECT));
62         std::string bundleName = element.GetBundleName();
63         std::string abilityName = element.GetAbilityName();
64         auto accountData = Singleton<AccessibleAbilityManagerService>::GetInstance().GetAccountData(accountId);
65         if (!accountData) {
66             Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
67                 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
68             HILOG_ERROR("accountData is nullptr.");
69             return;
70         }
71 
72         if (resultCode != NO_ERROR) {
73             accountData->RemoveEnabledAbility(Utils::GetUri(element));
74             accountData->RemoveConnectingA11yAbility(Utils::GetUri(element));
75             accountData->UpdateAbilities();
76             Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
77                 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
78             return;
79         }
80 
81         if (!remoteObject) {
82             Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
83                 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
84             HILOG_ERROR("AccessibleAbilityConnection::OnAbilityConnectDone get remoteObject failed");
85             return;
86         }
87 
88         sptr<AccessibleAbilityConnection> connection = accountData->GetConnectingA11yAbility(Utils::GetUri(element));
89         if (!connection) {
90             HILOG_ERROR("connection is nullptr");
91             return;
92         }
93 
94         accountData->AddConnectedAbility(connection);
95         accountData->RemoveConnectingA11yAbility(Utils::GetUri(element));
96         Singleton<AccessibleAbilityManagerService>::GetInstance().UpdateAccessibilityManagerService();
97         connection->InitAbilityClient(remoteObject);
98         accountData->UpdateEnableAbilityListsState();
99         }, "OnAbilityConnectDone");
100 }
101 
OnAbilityDisconnectDone(const AppExecFwk::ElementName & element,int32_t resultCode)102 void AccessibleAbilityConnection::OnAbilityDisconnectDone(const AppExecFwk::ElementName &element, int32_t resultCode)
103 {
104     HILOG_INFO("resultCode[%{public}d]", resultCode);
105     if (resultCode == NO_ERROR) {
106         return;
107     }
108     // when calling ConnectAbility function, OnAbilityDisconnectDone could be called when ability crashed
109     // and OnAbilityConnectDone won't be called. At this time, ConnectingA11yAbility should be cleaned up
110     if (!eventHandler_) {
111         HILOG_ERROR("eventHanlder_ is nullptr");
112         auto accountData = Singleton<AccessibleAbilityManagerService>::GetInstance().GetAccountData(accountId_);
113         if (accountData != nullptr) {
114             accountData->RemoveConnectingA11yAbility(Utils::GetUri(element));
115         }
116         return;
117     }
118 
119     int32_t accountId = accountId_;
120     eventHandler_->PostTask([accountId, element]() {
121         auto accountData = Singleton<AccessibleAbilityManagerService>::GetInstance().GetAccountData(accountId);
122         if (accountData != nullptr) {
123             accountData->RemoveConnectingA11yAbility(Utils::GetUri(element));
124         }
125         }, "OnAbilityDisconnectDone");
126 }
127 
OnAccessibilityEvent(AccessibilityEventInfo & eventInfo)128 void AccessibleAbilityConnection::OnAccessibilityEvent(AccessibilityEventInfo &eventInfo)
129 {
130     HILOG_DEBUG();
131     if (!abilityClient_) {
132         HILOG_ERROR("OnAccessibilityEvent​ failed");
133         return;
134     }
135 
136     std::vector<std::string> filterBundleNames = abilityInfo_.GetFilterBundleNames();
137     if (IsWantedEvent(eventInfo.GetEventType()) && (filterBundleNames.empty() || find(filterBundleNames.begin(),
138         filterBundleNames.end(), eventInfo.GetBundleName()) != filterBundleNames.end())) {
139         abilityClient_->OnAccessibilityEvent(eventInfo);
140         HILOG_DEBUG("windowId[%{public}d] evtType[%{public}d] windowChangeType[%{public}d] GestureId[%{public}d]",
141             eventInfo.GetWindowId(), eventInfo.GetEventType(), eventInfo.GetWindowChangeTypes(),
142             eventInfo.GetGestureType());
143     }
144 }
145 
OnKeyPressEvent(const MMI::KeyEvent & keyEvent,const int32_t sequence)146 bool AccessibleAbilityConnection::OnKeyPressEvent(const MMI::KeyEvent &keyEvent, const int32_t sequence)
147 {
148     if (!abilityClient_) {
149         HILOG_ERROR("OnKeyPressEvent failed");
150         return false;
151     }
152 
153     if (!(abilityInfo_.GetCapabilityValues() & Capability::CAPABILITY_KEY_EVENT_OBSERVER)) {
154         HILOG_ERROR("Capability failed");
155         return false;
156     }
157 
158     abilityClient_->OnKeyPressEvent(keyEvent, sequence);
159     return true;
160 }
161 
SetAbilityInfoTargetBundleName(const std::vector<std::string> & targetBundleNames)162 void AccessibleAbilityConnection::SetAbilityInfoTargetBundleName(const std::vector<std::string> &targetBundleNames)
163 {
164     HILOG_DEBUG();
165     abilityInfo_.SetFilterBundleNames(targetBundleNames);
166 }
167 
IsWantedEvent(int32_t eventType)168 bool AccessibleAbilityConnection::IsWantedEvent(int32_t eventType)
169 {
170     uint32_t type = static_cast<uint32_t>(eventType);
171     if ((type & abilityInfo_.GetEventTypes()) != type) {
172         HILOG_DEBUG("EventType(%{public}d) is not wanted", type);
173         return false;
174     }
175     return true;
176 }
177 
CreateWant(AppExecFwk::ElementName & element)178 AAFwk::Want CreateWant(AppExecFwk::ElementName& element)
179 {
180     AAFwk::Want want;
181     want.SetElement(element);
182 
183     return want;
184 }
185 
Disconnect()186 void AccessibleAbilityConnection::Disconnect()
187 {
188     HILOG_DEBUG();
189 
190     if (accountId_ == Singleton<AccessibleAbilityManagerService>::GetInstance().GetCurrentAccountId()) {
191         Singleton<AccessibleAbilityManagerService>::GetInstance().UpdateAccessibilityManagerService();
192     }
193 
194     if (!abilityClient_) {
195         HILOG_ERROR("abilityClient is nullptr");
196         return;
197     }
198     abilityClient_->Disconnect(connectionId_);
199 
200     auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
201     if (!abilityManagerClient) {
202         HILOG_ERROR("abilityManagerClient is nullptr");
203         return;
204     }
205     if (abilityManagerClient->DisconnectAbility(this) != ERR_OK) {
206         HILOG_ERROR("Disconnect failed!");
207         return;
208     }
209 }
210 
Connect(const AppExecFwk::ElementName & element)211 bool AccessibleAbilityConnection::Connect(const AppExecFwk::ElementName &element)
212 {
213     HILOG_DEBUG();
214     StartAsyncTrace(HITRACE_TAG_ACCESSIBILITY_MANAGER, "AccessibleAbilityConnect",
215         static_cast<int32_t>(TraceTaskId::ACCESSIBLE_ABILITY_CONNECT));
216     std::string bundleName = element.GetBundleName();
217     std::string abilityName = element.GetAbilityName();
218 
219     elementName_ = element;
220     HILOG_DEBUG("bundleName[%{public}s], abilityName [%{public}s], accountId [%{public}d]",
221         bundleName.c_str(), abilityName.c_str(), accountId_);
222 
223     auto bundleMgr = Singleton<AccessibleAbilityManagerService>::GetInstance().GetBundleMgrProxy();
224     if (!bundleMgr) {
225         Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
226             A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
227         HILOG_ERROR("get bundleMgr failed");
228         return false;
229     }
230     int uid = bundleMgr->GetUidByBundleName(bundleName, accountId_);
231     HILOG_DEBUG("uid is %{public}d ", uid);
232 
233     auto abilityManagerClient = AAFwk::AbilityManagerClient::GetInstance();
234     if (!abilityManagerClient) {
235         Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
236             A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
237         HILOG_ERROR("abilityManagerClient is nullptr");
238         return false;
239     }
240     AAFwk::Want want = CreateWant(elementName_);
241     if (abilityManagerClient->ConnectAbility(want, this, nullptr, uid / UID_MASK) != ERR_OK) {
242         Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
243             A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
244         HILOG_ERROR("ConnectAbility failed!");
245         return false;
246     }
247     return true;
248 }
249 
GetChannelId()250 int32_t AccessibleAbilityConnection::GetChannelId()
251 {
252     HILOG_DEBUG("connectionId_ is %{public}d", connectionId_);
253     return connectionId_;
254 }
255 
OnAbilityConnectDoneSync(const AppExecFwk::ElementName & element,const sptr<IRemoteObject> & remoteObject)256 void AccessibleAbilityConnection::OnAbilityConnectDoneSync(const AppExecFwk::ElementName &element,
257     const sptr<IRemoteObject> &remoteObject)
258 {
259     HILOG_DEBUG();
260     auto accountData = Singleton<AccessibleAbilityManagerService>::GetInstance().GetAccountData(accountId_);
261     if (!accountData) {
262         HILOG_ERROR("accountData is nullptr.");
263         return;
264     }
265     if (!remoteObject) {
266         HILOG_ERROR("AccessibleAbilityConnection::OnAbilityConnectDone get remoteObject failed");
267         return;
268     }
269     elementName_ = element;
270 
271     sptr<AccessibleAbilityConnection> pointer = this;
272     accountData->AddConnectedAbility(pointer);
273     Singleton<AccessibleAbilityManagerService>::GetInstance().UpdateAccessibilityManagerService();
274     InitAbilityClient(remoteObject);
275 }
276 
OnAbilityDisconnectDoneSync(const AppExecFwk::ElementName & element)277 void AccessibleAbilityConnection::OnAbilityDisconnectDoneSync(const AppExecFwk::ElementName &element)
278 {
279     HILOG_DEBUG();
280 
281     if (accountId_ == Singleton<AccessibleAbilityManagerService>::GetInstance().GetCurrentAccountId()) {
282         Singleton<AccessibleAbilityManagerService>::GetInstance().UpdateAccessibilityManagerService();
283     }
284 
285     if (!abilityClient_) {
286         HILOG_ERROR("abilityClient_ is nullptr");
287         return;
288     }
289     abilityClient_->Disconnect(connectionId_);
290 }
291 
InitAbilityClient(const sptr<IRemoteObject> & remoteObject)292 void AccessibleAbilityConnection::InitAbilityClient(const sptr<IRemoteObject> &remoteObject)
293 {
294     std::string bundleName = elementName_.GetBundleName();
295     std::string abilityName = elementName_.GetAbilityName();
296     abilityClient_ = new(std::nothrow) AccessibleAbilityClientProxy(remoteObject);
297     if (!abilityClient_) {
298         Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
299             A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
300         HILOG_ERROR("abilityClient_ is null");
301         return;
302     }
303 
304     if (!deathRecipient_) {
305         deathRecipient_ = new(std::nothrow) AccessibleAbilityConnectionDeathRecipient(
306             accountId_, elementName_, eventHandler_);
307         if (!deathRecipient_) {
308             Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
309                 A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
310             HILOG_ERROR("deathRecipient_ is null");
311             return;
312         }
313     }
314 
315     if (!abilityClient_->AsObject() || !abilityClient_->AsObject()->AddDeathRecipient(deathRecipient_)) {
316         HILOG_ERROR("Failed to add death recipient");
317     }
318 
319     channel_ = new(std::nothrow) AccessibleAbilityChannel(accountId_, abilityInfo_.GetId());
320     if (!channel_) {
321         Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
322             A11yError::ERROR_CONNECT_A11Y_APPLICATION_FAILED, bundleName, abilityName);
323         HILOG_ERROR("channel_ is null");
324         return;
325     }
326     abilityClient_->Init(channel_, connectionId_);
327 }
328 
OnRemoteDied(const wptr<IRemoteObject> & remote)329 void AccessibleAbilityConnection::AccessibleAbilityConnectionDeathRecipient::OnRemoteDied(
330     const wptr<IRemoteObject> &remote)
331 {
332     Utils::RecordUnavailableEvent(A11yUnavailableEvent::CONNECT_EVENT,
333         A11yError::ERROR_A11Y_APPLICATION_DISCONNECT_ABNORMALLY,
334         recipientElementName_.GetBundleName(), recipientElementName_.GetAbilityName());
335     if (!handler_) {
336         HILOG_ERROR("handler_ is nullptr");
337         return;
338     }
339     std::shared_ptr<AppExecFwk::ElementName> sharedElementName =
340         std::make_shared<AppExecFwk::ElementName>(recipientElementName_);
341 
342     if (sharedElementName == nullptr) {
343         HILOG_ERROR("sharedElementName is nullptr");
344         return;
345     }
346     int32_t accountId = accountId_;
347     handler_->PostTask([accountId, sharedElementName]() {
348         HILOG_DEBUG();
349 
350         auto &aams = Singleton<AccessibleAbilityManagerService>::GetInstance();
351         auto accountData = aams.GetAccountData(accountId);
352         if (!accountData) {
353             HILOG_ERROR("accountData is null.");
354             return;
355         }
356 
357         std::string uri = Utils::GetUri(*sharedElementName);
358         sptr<AccessibleAbilityConnection> connection = accountData->GetAccessibleAbilityConnection(uri);
359         if (!connection) {
360             HILOG_ERROR("There is no connection for %{public}s.", uri.c_str());
361             return;
362         }
363         accountData->RemoveConnectedAbility(*sharedElementName);
364         accountData->RemoveEnabledAbility(uri);
365 
366         std::string uiTestUri = Utils::GetUri("ohos.uitest", "uitestability");
367         if (uri == uiTestUri) {
368             accountData->RemoveInstalledAbility("ohos.uitest");
369         }
370 
371         accountData->UpdateAbilities();
372         aams.UpdateAccessibilityManagerService();
373         }, "OnRemoteDied");
374 }
375 } // namespace Accessibility
376 } // namespace OHOS