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